/**
 * PresenterFacade v1.5.7
 * (c) 2017 Jorson WHY
 * @license MIT
 */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
  typeof define === 'function' && define.amd ? define(['jquery'], factory) :
  (factory(global.jQuery));
}(this, (function (jQuery$1) { 'use strict';

jQuery$1 = 'default' in jQuery$1 ? jQuery$1['default'] : jQuery$1;

function assert(condition, msg) {
    if (condition) throw new Error("[midway] " + msg);
}

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  return typeof obj;
} : function (obj) {
  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};











var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

var createClass = function () {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  return function (Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
}();







var get = function get(object, property, receiver) {
  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent === null) {
      return undefined;
    } else {
      return get(parent, property, receiver);
    }
  } else if ("value" in desc) {
    return desc.value;
  } else {
    var getter = desc.get;

    if (getter === undefined) {
      return undefined;
    }

    return getter.call(receiver);
  }
};

var inherits = function (subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};











var possibleConstructorReturn = function (self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return call && (typeof call === "object" || typeof call === "function") ? call : self;
};

var templateRegExp = /\$\{(.+?)\}/g;
var hexDigits = "0123456789abcdefghijklmnopqrstuvwxyz";

var stringUtils = {
    applyTemplate: function applyTemplate(template, attrs) {
        return template.replace(templateRegExp, function ($0, $1) {
            return attrs[$1] || $0;
        });
    },
    createReg: function createReg(array) {
        return array.length ? new RegExp('^(' + array.join("|") + ')$') : /^$/;
    },
    uuid: function uuid(len) {
        var uuids = [];
        for (var i = 0; i < len; i++) {
            uuids[i] = hexDigits.substr(Math.floor(Math.random() * 36), 1);
        }
        return uuids.join('');
    },
    urlJoin: function urlJoin() {
        var input = arguments;
        var options = {};

        if (_typeof(arguments[0]) === 'object') {
            input = arguments[0];
            options = arguments[1] || {};
        }
        input = Array.prototype.compact.call(input);
        var joined = [].splice.call(input, 0).join('/');
        return normalize(joined, options);
    },
    randomWord: function randomWord(randomFlag, min, max) {
        var str = "",
            range = min,
            arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
        // 随机产生
        if (randomFlag) {
            range = Math.round(Math.random() * (max - min)) + min;
        }
        var pos = -1;
        for (var i = 0; i < range; i++) {
            pos = Math.round(Math.random() * (arr.length - 1));
            str += arr[pos];
        }
        return str;
    }
};

function startWith(str, search) {
    return str.substr(0, search.length) === search;
}

function normalize(str, options) {
    if (startWith(str, 'file://')) {
        str = str.replace(/(\/{0,3})\/*/g, '$1');
    } else {
        str = str.replace(/:\//g, '://');
        str = str.replace(/([^:\s\%\3\A])\/+/g, '$1/');
    }
    str = str.replace(/\/(\?|&|#[^!])/g, '$1');
    str = str.replace(/(\?.+)\?/g, '$1&');
    return str;
}

var SCENE_PATH_TEMPLATE = "${root}/resources/scene/config.json";

var SceneManager = function () {
    function SceneManager() {
        classCallCheck(this, SceneManager);

        if (!SceneManager.instance) {
            this.scenceCollection = {};
            SceneManager.instance = this;
        }
        return SceneManager.instance;
    }

    createClass(SceneManager, [{
        key: "getConfig",
        value: function getConfig(name, context) {
            var _this = this;

            var deferred = jQuery$1.Deferred();
            if (this.scenceCollection[name]) {
                //如果已经获取过了
                deferred.resolve({ config: this.scenceCollection[name] });
            } else {
                this._loadSceneConfig(context).done(function () {
                    deferred.resolve({ config: _this.scenceCollection[name] });
                });
            }
            return deferred.promise();
        }
    }, {
        key: "exists",
        value: function exists(name) {
            return !!this.scenceCollection[name];
        }
    }, {
        key: "_loadSceneConfig",
        value: function _loadSceneConfig(context) {
            var _this2 = this;

            var deferred = jQuery$1.Deferred();
            var basePath = context._trimSlash();
            var configPath = stringUtils.applyTemplate(SCENE_PATH_TEMPLATE, {
                "root": basePath ? basePath : "/"
            });
            jQuery$1.getJSON(configPath).done(function (config) {
                jQuery$1.each(config, function (key, value) {
                    if (_this2.scenceCollection[key] === undefined) {
                        _this2.scenceCollection[key] = value;
                    }
                });
                deferred.resolve();
            });
            return deferred.promise();
        }
    }]);
    return SceneManager;
}();

var sceneManager = new SceneManager();

var _head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;

var ScriptRender = {
    /**
     * 添加外部的URL引用
     * @param url 外部URL地址
     * @attrs 额外附加在style标签上的属性
     */
    addStyle: function addStyle() {
        var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        assert(url === undefined, "style url is undefined");
        var element = document.createElement('link');
        element.setAttribute('rel', 'stylesheet');
        element.setAttribute('type', 'text/css');
        element.setAttribute('href', url);
        if (attrs !== undefined) {
            for (var key in attrs) {
                script.setAttribute(key, attr[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    /**
     * 添加外部Javascript引用
     * @param url 外部JS地址
     * @attrs 额外附加在script标签上的属性
     */
    addJavascript: function addJavascript(url) {
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        assert(url === undefined, "script url is undefined");
        var deferred = $.Deferred(),
            script = document.createElement("script");
        script.type = 'text/javascript';
        script.charset = 'utf-8';
        script.async = true;
        script.src = url;
        if (attrs !== undefined) {
            for (var key in attrs) {
                script.setAttribute(key, attr[key]);
            }
        }
        script.onerror = function () {
            console.error("javascript load failure!, URL=" + url);
            deferred.reject();
        };
        script.onload = script.onreadystatechange = function (_, isAbort) {
            if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
                script.onload = script.onreadystatechange = null;
                script = null;
                if (!isAbort) {
                    deferred.resolve();
                } else {
                    deferred.reject();
                    console.error("load javascript abort!, URL=" + url);
                }
            }
        };
        _head.appendChild(script);
        return deferred.promise();
    },
    addEmbedStyle: function addEmbedStyle(code) {
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        var element = document.createElement("style");
        if (element.styleSheet) {
            element.styleSheet.cssText = code;
        } else {
            element.innerHTML = code;
        }
        if (attrs !== undefined) {
            for (var key in attrs) {
                element.setAttribute(key, attrs[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    addEmbedScript: function addEmbedScript(code) {
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        var element = document.createElement("script");
        element.setAttribute("language", "Javascript");
        element.text = code;
        if (attrs !== undefined) {
            for (var key in attrs) {
                element.setAttribute(key, attrs[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    /**
     * 检查外部样式是否引用
     * @param predicate 移除样式的依据, 可以是URL或函数
     * @returns {boolean} 引用情况
     */
    checkStyle: function checkStyle(predicate) {
        var exists = false;
        if (typeof predicate === 'string') {
            $.each(document.head.childNodes, function (index, item) {
                if (item.nodeName === 'LINK' && item.attributes['href'].value === predicate) {
                    exists = true;
                    return false;
                }
            });
        } else if (typeof predicate === 'function') {
            $.each(document.head.childNodes, function (index, item) {
                if ((item.nodeName === 'LINK' || item.nodeName === 'STYLE') && predicate.call(undefined, item)) {
                    exists = true;
                    return false;
                }
            });
        }
        return exists;
    },
    /**
     * 移除外接样式
     * @param predicate 移除样式的依据, 可以是URL或函数
     */
    removeStyle: function removeStyle(predicate) {
        if (typeof predicate === 'string') {
            var url = predicate;
            document.head.childNodes.forEach(function (item) {
                if (item.nodeName === 'LINK' && item.attributes['href'].value === url) {
                    _head.removeChild(item);
                }
            });
        } else if (typeof predicate === 'function') {
            document.head.childNodes.forEach(function (item) {
                if (item.nodeName === 'LINK' && predicate.call(undefined, item)) {
                    _head.removeChild(item);
                }
            });
        }
    },
    removeStyleElement: function removeStyleElement() {
        var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;

        assert(element === undefined, "style element is undefined");
        _head.removeChild(element);
        element = null;
    }
};

var ContextualLogger = function () {
    function ContextualLogger() {
        var defaultContext = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { filterLevel: LOG_LEVEL.OFF };
        classCallCheck(this, ContextualLogger);

        this.context = defaultContext;
        this.setLevel(defaultContext.filterLevel);
        this.logHandler = [];
    }

    createClass(ContextualLogger, [{
        key: 'setLevel',
        value: function setLevel(newLevel) {
            if (newLevel && "value" in newLevel) {
                this.context.filterLevel = newLevel;
            }
        }
    }, {
        key: 'enabledFor',
        value: function enabledFor(level) {
            var filterLevel = this.context.filterLevel;
            return level.value >= filterLevel.value;
        }
    }, {
        key: 'debug',
        value: function debug() {
            if (this.enabledFor(LOG_LEVEL.DEBUG)) {
                this.invoke(LOG_LEVEL.DEBUG, arguments);
            }
        }
    }, {
        key: 'info',
        value: function info() {
            if (this.enabledFor(LOG_LEVEL.INFO)) {
                this.invoke(LOG_LEVEL.INFO, arguments);
            }
        }
    }, {
        key: 'warn',
        value: function warn() {
            if (this.enabledFor(LOG_LEVEL.WARN)) {
                this.invoke(LOG_LEVEL.WARN, arguments);
            }
        }
    }, {
        key: 'error',
        value: function error() {
            if (this.enabledFor(LOG_LEVEL.ERROR)) {
                this.invoke(LOG_LEVEL.ERROR, arguments);
            }
        }
    }, {
        key: 'time',
        value: function time(label) {
            if (this.enabledFor(LOG_LEVEL.TIME)) {
                if (typeof label === 'string' && label.length > 0) {
                    this.invoke(LOG_LEVEL.TIME, [label, 'start']);
                }
            }
        }
    }, {
        key: 'timeEnd',
        value: function timeEnd(label) {
            if (this.enabledFor(LOG_LEVEL.TIME)) {
                if (typeof label === 'string' && label.length > 0) {
                    this.invoke(LOG_LEVEL.TIME, [label, 'end']);
                }
            }
        }
    }, {
        key: 'appendHandler',
        value: function appendHandler(handler, options) {
            if (options === undefined) {
                options = {};
            }
            //如果没有设置日志等级,使用默认的日志等级
            if (options.level === undefined) {
                options.level = this.context.filterLevel;
            }
            //如果没有设置formatter; 使用默认的formatter
            if (options.formatter === undefined) {
                options.formatter = defaultMessageFormatter;
            }
            //如果Handler和Formatter都存在且都是有效函数
            if (handler != undefined && typeof handler === "function") {
                if (options.formatter && typeof options.formatter === "function") {
                    $.extend(this.context, { filterLevel: options.level });
                    this.logHandler.push({ handle: handler, level: options.level, formatter: options.formatter });
                }
            }
        }
    }, {
        key: 'invoke',
        value: function invoke(level, msgArgs) {
            var _this = this;

            $.extend(this.context, { level: level });
            $.each(this.logHandler, function (index, item) {
                try {
                    if (level.value >= item.level.value) {
                        var messages = Array.prototype.slice.call(msgArgs);
                        item.formatter(messages, _this.context);
                        item.handle(messages, _this.context);
                    }
                } catch (e) {
                    //如果有错误,continue
                    console.log("LOGGER ERROR!", e);
                    return true;
                }
            });
        }
    }]);
    return ContextualLogger;
}();

function defaultMessageFormatter(messages, context) {
    if (context.name) {
        messages.unshift(new Date().toUTCString(), "(" + context.level.name + ")", "[" + context.name + "]");
    }
}

function merge() {
    var args = arguments,
        target = args[0],
        key = void 0,
        i = void 0;
    for (i = 1; i < args.length; i++) {
        for (key in args[i]) {
            if (!(key in target) && args[i].hasOwnProperty(key)) {
                target[key] = args[i][key];
            }
        }
    }
    return target;
}

var loggerManager = function loggerManager() {
    var contextualLoggersByNameMap = {};
    return {
        name: "Log Manager",
        version: "2.0.0",
        get: function get$$1(name) {
            if (name.toLowerCase() == "unknown") {
                return new ContextualLogger(merge({ name: name, filterLevel: LOG_LEVEL.OFF }));
            }
            if (contextualLoggersByNameMap[name]) {
                contextualLoggersByNameMap[name].logHandler = [];
                return contextualLoggersByNameMap[name];
            } else {
                contextualLoggersByNameMap[name] = new ContextualLogger(merge({
                    name: name,
                    filterLevel: LOG_LEVEL.OFF
                }));
                return contextualLoggersByNameMap[name];
            }
        }
    };
};

var LOG_LEVEL = {
    DEBUG: { value: 1, name: 'DEBUG' },
    INFO: { value: 2, name: 'INFO' },
    TIME: { value: 3, name: 'TIME' },
    WARN: { value: 4, name: 'WARN' },
    ERROR: { value: 8, name: 'ERROR' },
    OFF: { value: 99, name: 'OFF' }
};

var ConstVariable$1 = {
    PresenterType: {
        LAUNCHER: "presenterLauncher",
        CONTROLLER: "presenterController",
        LAYOUT: "presenterLayout",
        FUNCTIONAL: "presenterComponent"
    },
    PresenterBridge: {
        SMART_CLASS: "com.nd.pad.icr.ui.IcrJsBridge",
        HOMEWORK: "com.nd.android.homework.ui.HomeworkJsBridge",
        COURSEWARE: "CoursewareBridge"
    },
    PresenterEventType: {
        IC_PLAYER_EVENT: "ic_player_event", //ICPlayer事件总线类型
        NATIVE_EVENT: "native_event", //APP原生事件类型
        PPT_NATIVE_EVENT: "ppt_native_event" //应用于101PPT的原生事件类型
    },
    PresenterEventScope: {
        Global: 'global_bundle',
        Current: 'current_bundle'
    },
    PresenterLogLevel: {
        DEBUG: LOG_LEVEL.DEBUG,
        INFO: LOG_LEVEL.INFO,
        TIME: LOG_LEVEL.TIME,
        WARN: LOG_LEVEL.WARN,
        ERROR: LOG_LEVEL.ERROR,
        OFF: LOG_LEVEL.OFF
    }
};

var _arguments = arguments;
var supportFunction = {
    runSequence: function runSequence(fnConfigs, name) {
        var $promise = $.Deferred().resolve();
        var runIndex = void 0;

        fnConfigs.forEach(function (fnconfig, index) {
            if ($.isFunction(fnconfig.fn)) {
                $promise = $promise.then(function () {
                    try {
                        runIndex = index;
                        var callArgs = fnconfig.args || _arguments;
                        if (fnconfig.isAppendArgs === true) {
                            callArgs = Array.prototype.slice.call(_arguments, 0);
                            callArgs = callArgs.concat(fnConfig.args);
                        }
                        return fnconfig.fn.apply(fnconfig.scope || window, callArgs);
                    } catch (e) {
                        return $.Deferred(function (deferred) {
                            deferred.reject(e);
                        });
                    }
                }, function (message) {
                    return message;
                });
            }
        });

        return $promise.fail(function (e) {
            console.error("execute %s, number of %d error", name || "task", ++runIndex, e || "");
        });
    },

    execute: function execute(instance, injections, args, isCheck) {
        //参数整理
        var singleExecuteName = '';
        var result = {};
        if (typeof injections === 'string') {
            singleExecuteName = injections;
            injections = {};
            injections[singleExecuteName] = args || [];
        }
        if (instance) {
            for (var name in injections) {
                var fn = instance[name];
                if ($.isFunction(fn)) {
                    var params = injections[name];
                    var callMethod = $.isArray(params) ? 'apply' : 'call';
                    result[name] = Function.prototype[callMethod].call(fn, instance, params);
                } else if (isCheck === true) {
                    logger.error("不存在[" + name + ']方法');
                }
            }
        }
        return singleExecuteName ? result[singleExecuteName] : result;
    },

    createDelegate: function createDelegate(fn, args, isAppendArgs, scope, exceptionHandler) {
        return function () {
            //如果创建的时候没有输入参数，使用调用的参数
            var callArgs = args || _arguments;
            if (isAppendArgs === true) {
                //arguments数组化
                callArgs = Array.prototype.slice.call(_arguments, 0);
                callArgs = callArgs.concat(args);
            }
            try {
                return fn.apply(scope || window, callArgs);
            } catch (e) {
                if ($.isFunction(exceptionHandler)) {
                    return exceptionHandler(e);
                } else {
                    throw e;
                }
            }
        };
    },

    defer: function defer(millis, fn, args, appendArgs, scope) {
        var callFn = functionHelper.createDelegate(fn, args, appendArgs, scope);
        if (millis > 0) {
            return window.setTimeout(callFn, millis);
        }
        //直接调用，返回0的timerId
        callFn();
        return 0;
    },

    createPromiseThen: function createPromiseThen(deferred, fn, args, isAppendArgs, scope) {
        if (!$.isFunction(deferred.reject)) {
            scope = isAppendArgs;
            isAppendArgs = args;
            args = fn;
            fn = deferred;
            deferred = $.Deferred();
        }
        return supportFunction.createDelegate(fn, args, isAppendArgs, scope, function (e) {
            deferred.reject(e);
            return deferred.promise();
        });
    },

    isEmptyObject: function isEmptyObject(obj) {
        for (var name in obj) {
            return false;
        }
        return true;
    },

    isOwnEmptyObject: function isOwnEmptyObject(obj) {
        for (var name in obj) {
            if (obj.hasOwnProperty(name)) {
                return false;
            }
        }
        return true;
    },

    hasProp: function hasProp(obj, prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    },

    getOwn: function getOwn(obj, prop) {
        return obj && Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop];
    },

    defineProperty: function defineProperty(obj, key, value) {
        var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { configurable: false, enumerable: false, writable: false };

        Object.defineProperty(obj, key, {
            configurable: config.configurable || false,
            enumerable: config.enumerable || false,
            writable: config.writable || false,
            value: value
        });
    }
};

var requestParams = {
    params: {},
    get: function get() {
        return requestParams.params;
    }
};

var search = location.search;
search = search.substr(1, search.length);
var params = search.split('&');
params.forEach(function (name) {
    var p = name.split("=");
    var key = p[0];
    if (key) {
        requestParams.params[key] = decodeURIComponent(p[1]);
    }
});

var DEFAULT_LANGUAGE_CODE = "zh_CN";
var i18nInit = false;

var I18nManager = function () {
    function I18nManager() {
        classCallCheck(this, I18nManager);

        if (!I18nManager.instance) {
            this._languageConfig = {};
            this._languageSet = {};

            I18nManager.instance = this;
        }

        return I18nManager.instance;
    }

    createClass(I18nManager, [{
        key: "loadConfig",
        value: function loadConfig() {
            var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;

            var _this = this;

            var file = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'language.json';
            var async = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

            if (i18nInit) {
                console.warn("Internationalization Resource Manager did not initialization");
                return;
            }
            var cPath = stringUtils.urlJoin(MidwareConfig.BasePath, path, file, '?releaseNum=' + MidwareConfig.PlayerReleaseNumber);
            return jQuery$1.ajax({
                url: cPath,
                dataType: 'json',
                async: async
            }).done(function (data) {
                if (Array.prototype.isArray(data) && data.length > 0) {
                    var presenterConfig = data.filter(function (item) {
                        return item.type === "presenter";
                    });
                    //将配置转换为较容易识别的模式
                    presenterConfig.each(function (item) {
                        if (!_this._languageConfig[item.name]) {
                            //初始化配置集合
                            _this._languageConfig[item.name] = {};
                            //初始化语言集合
                            _this._languageSet[item.name] = {};
                            //初始化每个语言的集合
                            item.urls.each(function (lang) {
                                _this._languageConfig[item.name][lang.code] = lang.url;
                            });
                        }
                    });
                }
                //标记加载完成
                i18nInit = true;
                Object.freeze(_this);
            }).fail(function () {
                console.warn('language config file not loaded!');
            });
        }

        /**
         * 获取模块的国际化资源对象
         * @param key 资源键值
         * @param lang 语言编码
         * @param async 同步读取语言资源
         * @returns {JQueryPromise<T>}
         */

    }, {
        key: "loadLanguage",
        value: function loadLanguage(key, lang) {
            var _this2 = this;

            var async = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

            if (lang === undefined) {
                lang = DEFAULT_LANGUAGE_CODE;
            }
            assert(i18nInit === false, "language config not load");
            var deferred = jQuery$1.Deferred();
            if (!this._languageSet[key]) {
                //如果配置中不存在指定语言配置就直接返回
                deferred.resolve({ lang: undefined });
            } else {
                if (this._languageSet[key][lang]) {
                    //配置中存在且加载过
                    deferred.resolve({ lang: this._languageSet[key][lang] });
                } else {
                    //配置中存在但没有加载
                    var langUrl = stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.LanguageBasePath, this._languageConfig[key][lang], '?releaseNum=' + MidwareConfig.PlayerReleaseNumber);
                    jQuery$1.ajax({
                        url: langUrl,
                        async: async,
                        dataType: 'json'
                    }).done(function (langData) {
                        //需要经过版本检查
                        _this2._languageSet[key][lang] = _this2._versionCheck(key, langData);
                        deferred.resolve({ lang: _this2._languageSet[key][lang] });
                    }).fail(function () {
                        deferred.resolve({ lang: undefined });
                    });
                }
            }
            return deferred.promise();
        }

        /**
         * 替换指定View对象的语言文本
         * @param view View对象
         * @param langSet 语言对象
         */

    }, {
        key: "replaceView",
        value: function replaceView(view, langSet) {
            if (langSet === undefined || langSet === null) {
                return;
            }
            assert(i18nInit === false, "language config not load");
            var $view = !(view instanceof jQuery$1) ? $(view) : view;
            jQuery$1.each(langSet, function (key, value) {
                var items = $view.find('.lang_' + key);
                if (items.length > 0) {
                    items.text(value);
                }
            });
        }

        //提取

    }, {
        key: "_versionCheck",
        value: function _versionCheck(key, langSet) {
            var mVer = this._getVersionValue(CustomPlayerConfig.Presenters[key].version);
            var versionRes = {};

            for (var _key in langSet) {
                if (_key.indexOf('@') > 0) {
                    var temp = _key.split('@');
                    if (versionRes[temp[0]] === undefined) {
                        versionRes[temp[0]] = [];
                        versionRes[temp[0]].push({
                            key: 0,
                            value: langSet[temp[0]]
                        });
                    }
                    var verValue = this._getVersionValue(temp[1]);
                    for (var i = 0, len = versionRes[temp[0]].length; i < len; i++) {
                        if (verValue < versionRes[temp[0]][i].key) {
                            versionRes[temp[0]].insertOf(i, { key: verValue, value: langSet[_key] });
                            break;
                        }
                        if (i === len - 1) {
                            versionRes[temp[0]].push({ key: verValue, value: langSet[_key] });
                        }
                    }
                    //移除所有带版本的Key
                    delete langSet[_key];
                }
            }

            if (supportFunction.isEmptyObject(versionRes)) {
                return langSet;
            }
            //确认所有有版本的Key最终应该使用那个
            for (var _key2 in versionRes) {
                var tempArray = versionRes[_key2];
                for (var _i = 0; _i < tempArray.length; _i++) {
                    if (tempArray[_i].key === mVer) {
                        //能够找到对应版本, 直接使用
                        langSet[_key2] = tempArray[_i].value;
                        break;
                    }
                    if (tempArray[_i].key > mVer && _i !== 0) {
                        //能够找到比当前版本大的版本, 使用前一个版本的值
                        langSet[_key2] = tempArray[_i - 1].value;
                        break;
                    }
                    //当前版本比所有配置版本都大, 使用最后一个版本的值
                    langSet[_key2] = tempArray[_i].value;
                }
            }
            return langSet;
        }
        //获取版本的分值,按照3位版本, 每个版本2位数计算

    }, {
        key: "_getVersionValue",
        value: function _getVersionValue(version) {
            var temp = version.split('.');
            if (temp.length !== 3) {
                return -1;
            }
            return temp[0] * 10000 + temp[1] * 100 + temp[2] * 1;
        }
    }, {
        key: "CurrentLanguage",
        get: function get$$1() {
            return requestParams.params["_lang_"] === undefined ? DEFAULT_LANGUAGE_CODE : requestParams.params["_lang_"];
        }
    }]);
    return I18nManager;
}();

var i18nManager = new I18nManager();

var WekMapPolyFill = function () {
    function WekMapPolyFill() {
        classCallCheck(this, WekMapPolyFill);

        if (this === void 0) {
            throw new TypeError("Constructor WeakMap requires 'new'");
        }
        this._id = genId('_WeakMap');
        this._polyfill = true;
        if (arguments.length > 0) {
            throw new TypeError('WeakMap iterable is not supported');
        }
    }

    createClass(WekMapPolyFill, [{
        key: 'delete',
        value: function _delete(key) {
            checkInstance(this, 'delete');

            if (!isObject(key)) {
                return false;
            }

            var entry = key[this._id];
            if (entry && entry[0] === key) {
                delete key[this._id];
                return true;
            }

            return false;
        }
    }, {
        key: 'get',
        value: function get$$1(key) {
            checkInstance(this, 'get');

            if (!isObject(key)) {
                return void 0;
            }

            var entry = key[this._id];
            if (entry && entry[0] === key) {
                return entry[1];
            }

            return void 0;
        }
    }, {
        key: 'has',
        value: function has(key) {
            checkInstance(this, 'has');

            if (!isObject(key)) {
                return false;
            }

            var entry = key[this._id];
            return !!(entry && entry[0] === key);
        }
    }, {
        key: 'set',
        value: function set$$1(key, value) {
            checkInstance(this, 'set');

            if (!isObject(key)) {
                throw new TypeError('Invalid value used as weak map key');
            }

            var entry = key[this._id];
            if (entry && entry[0] === key) {
                entry[1] = value;
                return this;
            }

            defineProperty$1(key, this._id, [key, value]);
            return this;
        }
    }]);
    return WekMapPolyFill;
}();

function defineProperty$1(object, name, value) {
    if (Object.defineProperty) {
        Object.defineProperty(object, name, {
            configurable: true,
            writable: true,
            value: value
        });
    } else {
        object[name] = value;
    }
}

function checkInstance(x, methodName) {
    if (!isObject(x) || !Object.prototype.hasOwnProperty.call(x, '_id')) {
        throw new TypeError(methodName + ' method called on incompatible receiver ' + (typeof x === 'undefined' ? 'undefined' : _typeof(x)));
    }
}

function isObject(x) {
    return Object(x) === x;
}

function genId(prefix) {
    return prefix + '_' + rand() + '.' + rand();
}

function rand() {
    return Math.random().toString().substring(2);
}

//poly fill
if (!window.WeakMap) {
    window.WeakMap = WekMapPolyFill;
}

//样式路径
var _styleAssetPath = new WeakMap();

var StyleManager = function () {
    function StyleManager() {
        classCallCheck(this, StyleManager);

        if (!StyleManager.instance) {
            this._styleConfig = {};
            this._loadedStyle = {};
            this._courseobjectToSkin = {};
            this._containVersion = false;

            StyleManager.instance = this;
        }

        return StyleManager.instance;
    }

    /**
     * 加载样式配置并转换为更容易处理的结构
     * @param path 样式库配置位置
     * @param file 样式库配置文件
     * @param async 同步读取配置
     * @param version 样式库路径是否包含版本
     */


    createClass(StyleManager, [{
        key: "loadConfig",
        value: function loadConfig() {
            var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
            var file = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'style.config.json';

            var _this = this;

            var async = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
            var version = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

            if (!supportFunction.isOwnEmptyObject(this._styleConfig)) {
                console.info("style config has been loaded! can't load repeatedly!!");
                return;
            }
            _styleAssetPath.set(this, stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.AssetsBasePath));
            var configPath = stringUtils.urlJoin(MidwareConfig.BasePath, path, file, '?releaseNum=' + MidwareConfig.PlayerReleaseNumber);
            return jQuery$1.ajax({
                url: configPath,
                dataType: 'json',
                async: async
            }).done(function (styleConfigs) {
                for (var key in styleConfigs) {
                    var config = styleConfigs[key];
                    if (config.styles && Array.prototype.isArray(config.styles)) {
                        config.styles.forEach(function (style) {
                            //设置默认值
                            if (style.default === undefined) {
                                style['default'] = {
                                    app: 'pptshell',
                                    skin: '__default',
                                    language: 'zh_CN'
                                };
                            }
                            var cfg = void 0;
                            for (var i = 0, len = style.configs.length; i < len; i++) {
                                cfg = style.configs[i];
                                cfg.link += '?releaseNum=' + MidwareConfig.PlayerReleaseNumber + "";
                            }
                        });
                    }
                }
                _this._styleConfig = styleConfigs;
                _this._containVersion = version;
            }).fail(function () {
                console.warn("can't load style config file!");
            });
        }

        /**
         * 释放颗粒加载的样式
         * @param name 颗粒名称
         */

    }, {
        key: "releaseStyle",
        value: function releaseStyle(name) {
            for (var key in this._loadedStyle) {
                //找到对应颗粒
                if (key.indexOf(name) === 0) {
                    var setting = this._loadedStyle[key];
                    if (setting.loaded) {
                        setting.elements.forEach(function (ele) {
                            ScriptRender.removeStyleElement(ele);
                        });
                        setting.elements = [];
                        setting.loaded = false;
                    }
                }
            }
        }

        /**
         * 加载颗粒样式
         * @param name 颗粒名称
         * @param scene 场景名称
         * @param skin 皮肤
         * @param lang 语言
         */

    }, {
        key: "loadStyle",
        value: function loadStyle(name, scene, skin, lang) {
            var _this2 = this;

            //验证输入参数
            assert(name === undefined, 'the style library name is empty');
            if (!supportFunction.hasProp(this._styleConfig, name)) {
                console.warn('specified courseware object are not configured with style libraries');
                return;
            }
            var styleKey = name + '_' + scene + '_' + skin + '_' + lang;
            if (!supportFunction.hasProp(this._loadedStyle, styleKey)) {
                //还没有提取加载
                this._loadedStyle[styleKey] = { loaded: false, styles: [], elements: [] };
                var styles = this._styleConfig[name].styles;
                styles.forEach(function (style) {
                    var filter = {
                        app: scene || style.default.app, skin: skin || style.default.skin,
                        language: lang || style.default.language
                    };
                    var config = style.configs.find(function (item) {
                        return item.app === filter.app && item.skin === filter.skin && item.language.indexOf(filter.language) >= 0;
                    });
                    if (config !== undefined) {
                        if (_this2._containVersion) {
                            //需要包含版本
                            config.link = config.link.insert(config.link.indexOf(style.code) + style.code.length, '/' + style.version);
                        }
                        _this2._loadedStyle[styleKey].styles.push(stringUtils.applyTemplate(config.link, { 'assets': _styleAssetPath.get(_this2) }));
                    }
                });
            }
            var setting = this._loadedStyle[styleKey];
            if (!setting.loaded && setting.styles.length > 0) {
                setting.styles.forEach(function (item) {
                    var styleEle = ScriptRender.addStyle(item);
                    setting.elements.push(styleEle);
                });
                setting.loaded = true;
                this._courseobjectToSkin[name] = styleKey;
            }
        }

        /**
         * 改变颗粒样式
         * @param name 样式名称
         * @param scene 当前场景
         * @param skin 皮肤
         * @param lang 语言
         */

    }, {
        key: "changeStyle",
        value: function changeStyle(name, scene, skin, lang) {
            var styleKey = name + '_' + scene + '_' + skin + '_' + lang;
            if (this._courseobjectToSkin[name] === styleKey) {
                console.info("the specified style library configuration has been loaded");
                return;
            }
            //移除已经存在的样式库
            this._removeStyle(this._courseobjectToSkin[name]);
            //加载待加载的样式库
            this.loadStyle(name, scene, skin, lang);
        }
    }, {
        key: "_removeStyle",
        value: function _removeStyle(styleKey) {
            var setting = this._loadedStyle[styleKey];
            if (setting.loaded) {
                setting.elements.forEach(function (ele) {
                    ScriptRender.removeStyleElement(ele);
                });
                setting.elements = [];
                setting.loaded = false;
            }
        }
    }]);
    return StyleManager;
}();

var styleManager = new StyleManager();

var BasicManager = function () {
    function BasicManager() {
        classCallCheck(this, BasicManager);

        this.collection = {};
    }

    createClass(BasicManager, [{
        key: "add",
        value: function add(name, item) {
            assert(item === undefined, "manage item can't NULL!");
            if (this.collection[name] === undefined) {
                this.collection[name] = item;
            }
        }
    }, {
        key: "get",
        value: function get$$1(name) {
            if (this.collection[name]) {
                return this.collection[name];
            }
            return undefined;
        }
    }, {
        key: "exists",
        value: function exists(name) {
            return !(this.collection[name] === undefined);
        }
    }, {
        key: "remove",
        value: function remove(name) {
            if (this.collection[name]) {
                this.beforeRemove(this.collection[name]);
                this.collection[name] = null;
                delete this.collection[name];
                this.afterRemove();
            }
        }
    }, {
        key: "release",
        value: function release() {
            for (var key in this.collection) {
                delete this.collection[key];
            }
            this.collection = null;
        }
    }, {
        key: "each",
        value: function each(fn) {
            if (typeof fn !== 'function') {
                return;
            }
            for (var key in this.collection) {
                fn.call(this, key, this.collection[key]);
            }
        }
    }, {
        key: "beforeRemove",
        value: function beforeRemove(item) {}
    }, {
        key: "afterRemove",
        value: function afterRemove() {}
    }]);
    return BasicManager;
}();

var coursewareConfigInit = false;

var CoursewareConfigManager = function (_BasicManager) {
    inherits(CoursewareConfigManager, _BasicManager);

    function CoursewareConfigManager() {
        var _ret;

        classCallCheck(this, CoursewareConfigManager);

        if (!CoursewareConfigManager.instance) {
            var _this = possibleConstructorReturn(this, (CoursewareConfigManager.__proto__ || Object.getPrototypeOf(CoursewareConfigManager)).call(this));

            CoursewareConfigManager.instance = _this;
        }

        return _ret = CoursewareConfigManager.instance, possibleConstructorReturn(_this, _ret);
    }

    createClass(CoursewareConfigManager, [{
        key: "loadConfig",
        value: function loadConfig() {
            var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;

            var _this2 = this;

            var file = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'coursesubject.json';
            var async = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

            if (coursewareConfigInit) {
                return;
            }
            var cPath = stringUtils.urlJoin(MidwareConfig.BasePath, path, file, '?releaseNum=' + MidwareConfig.PlayerReleaseNumber);
            return jQuery$1.ajax({
                url: cPath,
                dataType: 'json',
                async: async
            }).done(function (data) {
                _this2.collection = data;
                coursewareConfigInit = true;
            }).fail(function () {
                console.warn('courseware object config load error!!');
            });
        }
    }]);
    return CoursewareConfigManager;
}(BasicManager);

var coursewareConfigManager = new CoursewareConfigManager();

var BaseRenderLibraryStrategy = function () {
    function BaseRenderLibraryStrategy() {
        classCallCheck(this, BaseRenderLibraryStrategy);

        this.settings = undefined;
        this.renders = [];
        if (MidwareConfig.extend && MidwareConfig.extend[MidwareConfig.RunEnvironment]) {
            this.settings = MidwareConfig.extend[MidwareConfig.RunEnvironment];
        }
        this.configBasePath = this.settings && this.settings.path ? this.settings.path.LifeCycleBaseUrl : 'https://esp-lifecycle.sdp.101.com/v0.6';
        this.renders = this.settings.renders || [];
    }

    createClass(BaseRenderLibraryStrategy, [{
        key: "$getResourceCode",
        value: function $getResourceCode(metaData) {
            if (metaData['categories'] && metaData['categories']['res_type']) {
                var resType = metaData['categories']['res_type'];
                if (resType instanceof Array) {
                    var _iteratorNormalCompletion = true;
                    var _didIteratorError = false;
                    var _iteratorError = undefined;

                    try {
                        for (var _iterator = resType[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                            var item = _step.value;

                            if (item.indexOf("$RE") === 0 && item[item.length - 1] !== '0') {
                                return item;
                            }
                        }
                    } catch (err) {
                        _didIteratorError = true;
                        _iteratorError = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion && _iterator.return) {
                                _iterator.return();
                            }
                        } finally {
                            if (_didIteratorError) {
                                throw _iteratorError;
                            }
                        }
                    }
                }
            }
            return null;
        }
    }, {
        key: "$findRenderCode",
        value: function $findRenderCode(key, code) {
            var renderInfo = this.renders.find(function (item) {
                if (item[key]) {
                    return item[key] === code;
                }
                return false;
            });
            if (renderInfo) {
                return renderInfo.render;
            }
            return null;
        }
    }, {
        key: "$loadUrl",
        value: function $loadUrl(url, async, doneFn, failFn, options) {
            return jQuery$1.ajax({
                url: url,
                method: 'GET',
                cache: false,
                async: async
            }).done(function (data) {
                if (typeof doneFn === 'function') {
                    doneFn(data, options);
                }
            }).fail(function (xhr, status, error) {
                failFn(xhr, status, error, options);
            });
        }
    }]);
    return BaseRenderLibraryStrategy;
}();

var DirectRenderLibraryStrategy = function (_BaseRenderLibraryStr) {
    inherits(DirectRenderLibraryStrategy, _BaseRenderLibraryStr);

    function DirectRenderLibraryStrategy(options) {
        classCallCheck(this, DirectRenderLibraryStrategy);

        var _this = possibleConstructorReturn(this, (DirectRenderLibraryStrategy.__proto__ || Object.getPrototypeOf(DirectRenderLibraryStrategy)).call(this));

        if (!options.questionType) {
            //TODO: error message
            throw Error();
        }
        _this.questionType = options.questionType;
        return _this;
    }

    createClass(DirectRenderLibraryStrategy, [{
        key: "getRenderLibraryCode",
        value: function getRenderLibraryCode() {
            var info = undefined,
                code = this.$findRenderCode("questionType", this.questionType);
            if (code !== null) {
                info = { id: stringUtils.randomWord(false, 12), code: code };
            }
            return info;
        }
    }]);
    return DirectRenderLibraryStrategy;
}(BaseRenderLibraryStrategy);

var IdentifyRenderLibraryStrategy = function (_BaseRenderLibraryStr2) {
    inherits(IdentifyRenderLibraryStrategy, _BaseRenderLibraryStr2);

    function IdentifyRenderLibraryStrategy(options) {
        classCallCheck(this, IdentifyRenderLibraryStrategy);

        var _this2 = possibleConstructorReturn(this, (IdentifyRenderLibraryStrategy.__proto__ || Object.getPrototypeOf(IdentifyRenderLibraryStrategy)).call(this));

        if (!options.questionId) {
            //TODO: error message
            throw Error();
        }
        //习题ID
        _this2.questionId = options.questionId;
        //习题分类
        _this2.questionClassify = options.questionClassify;

        _this2.classifyMapping = {
            interactive: "coursewareobjects",
            basic: "questions"
        };
        return _this2;
    }

    createClass(IdentifyRenderLibraryStrategy, [{
        key: "getRenderLibraryCode",
        value: function getRenderLibraryCode() {
            var basicMetaInfo = void 0,
                interactiveMetaInfo = '';
            if (this.questionClassify) {
                basicMetaInfo = stringUtils.urlJoin(this.configBasePath, this.classifyMapping[this.questionClassify], this.questionId, '?include=TI&isAll=false');
            } else {
                basicMetaInfo = stringUtils.urlJoin(this.configBasePath, this.classifyMapping['basic'], this.questionId, '?include=TI&isAll=false');
                interactiveMetaInfo = stringUtils.urlJoin(this.configBasePath, this.classifyMapping['interactive'], this.questionId, '?include=TI&isAll=false');
            }

            this.$loadUrl(basicMetaInfo, false, this._onSuccess.bind(this), this._onFail.bind(this), { nextUrl: interactiveMetaInfo });
        }
    }, {
        key: "_onSuccess",
        value: function _onSuccess(data, options) {
            var resCode = this.$getResourceCode(data);
            if (resCode !== null) {
                return this.$findRenderCode('resCode', resCode);
            } else {
                if (options && options.nextUrl) {
                    this.$loadUrl(options.nextUrl, false, this._onSuccess.bind(this), this._onFail.bind(this));
                } else {
                    //TODO: error message
                    throw Error();
                }
            }
        }
    }, {
        key: "_onFail",
        value: function _onFail() {}
    }]);
    return IdentifyRenderLibraryStrategy;
}(BaseRenderLibraryStrategy);

var UrlRenderLibraryStrategy = function (_BaseRenderLibraryStr3) {
    inherits(UrlRenderLibraryStrategy, _BaseRenderLibraryStr3);

    function UrlRenderLibraryStrategy(options) {
        classCallCheck(this, UrlRenderLibraryStrategy);

        var _this3 = possibleConstructorReturn(this, (UrlRenderLibraryStrategy.__proto__ || Object.getPrototypeOf(UrlRenderLibraryStrategy)).call(this));

        if (!options.questionUrl) {
            //TODO: error message
            throw Error();
        }
        _this3.questionUrl = options.questionUrl;
        return _this3;
    }

    createClass(UrlRenderLibraryStrategy, [{
        key: "getRenderLibraryCode",
        value: function getRenderLibraryCode() {
            this.$loadUrl(stringUtils.urlJoin(this.questionUrl, 'metadata.json', this._onSuccess.bind(this), function () {
                //TODO: error message
                throw Error();
            }));
        }
    }, {
        key: "_onSuccess",
        value: function _onSuccess(data) {
            var resCode = this.$getResourceCode(data);
            if (resCode !== null) {
                return this.$findRenderCode('resCode', resCode);
            } else {
                //TODO: error message
                throw Error();
            }
        }
    }]);
    return UrlRenderLibraryStrategy;
}(BaseRenderLibraryStrategy);

var BaseWrap = function BaseWrap() {
    classCallCheck(this, BaseWrap);
};

function Observer() {
    return function (target) {
        if (!target.prototype.hasOwnProperty('subscribers')) {
            Object.defineProperty(target.prototype, 'subscribers', {
                value: {}
            });
        }
        if (!target.prototype.hasOwnProperty('addSubscriber')) {
            Object.defineProperty(target.prototype, "addSubscriber", {
                value: function value(key, fn) {
                    if (typeof fn !== 'function') {
                        console.warn("subscriber not a function");
                        return;
                    }

                    if (this.subscribers[key] === undefined) {
                        this.subscribers[key] = [];
                    }
                    this.subscribers[key].push(fn);
                }
            });
        }
        if (!target.prototype.hasOwnProperty('removeSubscriber')) {
            Object.defineProperty(target.prototype, "removeSubscriber", {
                value: function value(key, fn) {
                    if (this.subscribers[key] === undefined) {
                        console.warn("subscriber not exists!");
                        return;
                    }
                    for (var i = 0, len = this.subscribers[key].length; i < len; i++) {
                        if (this.subscribers[key][i] === fn) {
                            this.subscribers[key].splice(i, 1);
                        }
                    }
                }
            });
        }
        if (!target.prototype.hasOwnProperty('publish')) {
            Object.defineProperty(target.prototype, "publish", {
                value: function value(key, what) {
                    if (this.subscribers[key] === undefined) {
                        console.warn("subscriber not exists!");
                        return;
                    }

                    for (var i = 0, len = this.subscribers[key].length; i < len; i++) {
                        if (typeof this.subscribers[key][i] === 'function') {
                            this.subscribers[key][i](what);
                        }
                    }
                }
            });
        }
    };
}

var _dec$1;
var _class$1;

var innerBundleCollection = new WeakMap();

var RenderWrap = (_dec$1 = Observer(), _dec$1(_class$1 = function (_BaseWrap) {
    inherits(RenderWrap, _BaseWrap);

    function RenderWrap(options) {
        var _ret;

        classCallCheck(this, RenderWrap);

        var _this = possibleConstructorReturn(this, (RenderWrap.__proto__ || Object.getPrototypeOf(RenderWrap)).call(this));

        _this.hasBeenInit = false;
        _this.currentId = options.id;
        _this.code = options.code;
        var bundle = new Midway.Bundle({
            launcher: options.code,
            model: options.model
        });
        innerBundleCollection.set(_this, bundle);
        var ready = jQuery$1.Deferred();
        bundle.start(function () {
            _this.hasBeenInit = true;
            _this._appendBundleMethod(options.prefix);
            ready.resolve(_this);
        });
        return _ret = ready.promise(), possibleConstructorReturn(_this, _ret);
    }

    createClass(RenderWrap, [{
        key: "changeModel",
        value: function changeModel(model) {
            assert(this.hasBeenInit === false, "init not complete");
            innerBundleCollection.get(this).update(model);
        }
    }, {
        key: "invoke",
        value: function invoke(method) {
            assert(this.hasBeenInit === false, "init not complete");

            if (typeof method !== 'string') {
                console.error('method must a string!');
            }

            var bundle = innerBundleCollection.get(this);

            for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
                args[_key - 1] = arguments[_key];
            }

            return bundle.invoke(method, args);
        }
    }, {
        key: "release",
        value: function release() {
            assert(this.hasBeenInit === false, "init not complete");
            innerBundleCollection.get(this).release();
            innerBundleCollection.delete(this);
            this.hasBeenInit = false;
            //发出被release的消息
            this.publish("render-wrap-release", this.code);
        }

        //只能从Launcher模块中进行转接

    }, {
        key: "_appendBundleMethod",
        value: function _appendBundleMethod(prefix) {
            var bundle = innerBundleCollection.get(this);
            var launcherInstance = bundle.Processors[0].ModuleInstance;
            for (var key in launcherInstance) {
                if (key.indexOf(prefix) === 0 && this[key] === undefined) {
                    this[key] = launcherInstance[key];
                }
            }
        }
    }, {
        key: "CurrentId",
        get: function get$$1() {
            return this.currentId;
        },
        set: function set$$1(id) {
            this.currentId = id;
        }
    }]);
    return RenderWrap;
}(BaseWrap)) || _class$1);

var WrapManager = function (_BasicManager) {
    inherits(WrapManager, _BasicManager);

    function WrapManager() {
        var _ret;

        classCallCheck(this, WrapManager);

        if (!WrapManager.instance) {
            var _this = possibleConstructorReturn(this, (WrapManager.__proto__ || Object.getPrototypeOf(WrapManager)).call(this));

            WrapManager.instance = _this;
        }
        return _ret = WrapManager.instance, possibleConstructorReturn(_this, _ret);
    }

    /**
     * 获取颗粒渲染包装器
     * @param options 配置
     */


    createClass(WrapManager, [{
        key: "getRenderWrapper",
        value: function getRenderWrapper(options) {
            var _this2 = this;

            //获取对应渲染器的Code
            var strategy = choseRenderStrategy(options.question);
            var info = strategy.getRenderLibraryCode();
            if (!info) {
                //TODO: error message
                throw Error("");
            }
            var wrapDef = jQuery$1.Deferred();
            if (this.exists(info.code)) {
                var renderWrap = this.get(info.code);
                if (renderWrap.CurrentId !== info.id) {
                    //数据不同, 改变数据
                    renderWrap.changeModel(options.model);
                    renderWrap.CurrentId = info.id;
                }
                wrapDef.resolve(renderWrap);
            } else {
                new RenderWrap({
                    code: info.code,
                    model: options.model || {},
                    prefix: options.prefix || "render"
                }).then(function (wrap) {
                    wrap.addSubscriber('render-wrap-release', _this2.remove.bind(_this2));
                    _this2.add(info.code, wrap);
                    wrapDef.resolve(wrap);
                });
            }
            return wrapDef.promise();
        }

        /**
         * 获取颗粒注入包装器
         * @param options 配置
         */

    }, {
        key: "getInjectorWrapper",
        value: function getInjectorWrapper(options) {
            throw Error("Not Implementation!");
        }
    }]);
    return WrapManager;
}(BasicManager);

function choseRenderStrategy(options) {
    if (options.questionType && typeof options.questionType === 'string') {
        return new DirectRenderLibraryStrategy(options);
    } else if (options.questionId && typeof options.questionId === 'string') {
        return new IdentifyRenderLibraryStrategy(options);
    } else if (options.questionUrl && typeof options.questionUrl === 'string') {
        return new UrlRenderLibraryStrategy(options);
    }
}

var wrapManager = new WrapManager();

/**
 * 获取定制播放器的配置信息
 */
function getPlayerConfig(envConfig, code, version, file) {
    var async = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;

    var configPath = void 0;
    if (envConfig.Online === false) {
        configPath = stringUtils.urlJoin(envConfig.ConfigPath || "configuration", file);
    } else {
        //开发环境下
        if (envConfig.RunEnvironment === 'development') {} else {
            if (code === undefined || version === undefined) {
                throw Error("invalid arguments");
            }
            configPath = stringUtils.urlJoin(envConfig.BasePath, 'players', code, version, file);
        }
    }

    return jQuery$1.ajax({
        url: configPath,
        dataType: 'json',
        method: 'GET',
        cache: false,
        async: async
    });
}

var extendModuleContexts = {};

var extendModuleRequire = function extendModuleRequire(key, context) {
    var defaultCtx = '_';
    if (typeof context === 'string') {
        defaultCtx = context;
    }
    var ctx = getOwn(extendModuleContexts, defaultCtx);
    if (!ctx) {
        throw new Error('context not exists');
    }
    ctx.load(key);
    return extendModuleContexts[defaultCtx].getDef(key);
};

var extendModuleRelease = function extendModuleRelease(key, context) {
    var defCtx = '_';
    if (typeof context === 'string') {
        defCtx = context;
    }
    var ctx = getOwn(extendModuleContexts, defCtx);
    if (!ctx) {
        throw new Error('context not exists');
    }
    ctx.unload(key);
};

var extendModuleDefine = function extendModuleDefine(key, main, context, scope) {
    var defaultContext = '_';
    if (typeof context === 'string' && !main) {
        defaultContext = context;
    }
    if (typeof main !== 'function' && typeof context === 'function') {
        main = context;
    }
    var ctx = getOwn(extendModuleContexts, defaultContext);
    if (ctx) {
        ctx.pushQueue(key, main, scope);
    }
};

var EXTEND_MODULE_TYPE = {
    ExtendModule: 'ExtendModule',
    StyleResource: 'StyleResource',
    MaterialResource: 'MaterialResource'
};

var extendModule = {
    config: function config(cfg) {
        if (cfg.context) {
            var existingContext = getOwn(extendModuleContexts, cfg.context);
            if (existingContext) {
                //reConfig existing context
                existingContext.config(cfg);
            } else {
                //config new context
                extendModuleContexts[cfg.context] = new ExtendModuleContext(cfg.context, cfg);
            }
            return cfg.context;
        }
        throw new Error('');
    },
    getBasePath: function getBasePath() {
        var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '_';

        var existingContext = getOwn(extendModuleContexts, context);
        if (existingContext) {
            return extendModuleContexts[context].Config.baseUrl;
        }
        return undefined;
    },
    isBrowser: function isBrowser() {
        return typeof document !== 'undefined' && typeof navigator !== 'undefined';
    }
};

var ExtendModuleContext = function () {
    function ExtendModuleContext(name, config) {
        classCallCheck(this, ExtendModuleContext);

        this._name = name;
        this._defaultConfig = {
            waitSeconds: 7,
            baseUrl: './'
        };
        if (config) {
            this._config = jQuery$1.extend(true, this._defaultConfig, config);
        }
        this._extendConfig = {};
        this._deferreds = {};
        this._requires = {};
        this._queue = [];
        this._cache = {};
    }

    createClass(ExtendModuleContext, [{
        key: "config",
        value: function config(cfg) {
            if (cfg && cfg.context === this._name) {
                this._name = cfg.context;
                jQuery$1.extend(true, this._config, cfg);
            }
        }

        /**
         * 加载扩展模块
         * @param key 扩展模块的键值
         */

    }, {
        key: "load",
        value: function load(key) {
            var _this = this;

            //构建延迟对象
            this._makeDef(key);
            //扩展模块配置
            var extendConfig = null;
            this._getModuleConfig(key).done(function (data) {
                if (data.config) {
                    extendConfig = data.config;
                } else {
                    extendConfig = data;
                    _this._extendConfig[key] = extendConfig;
                }

                switch (extendConfig.type) {
                    case EXTEND_MODULE_TYPE.ExtendModule:
                        //扩展模块处理main和style配置
                        if (extendConfig.style) {
                            //加载样式
                            var styleUrl = stringUtils.urlJoin(_this._config.baseUrl, key, extendConfig.style);
                            if (!ScriptRender.checkStyle(styleUrl)) {
                                ScriptRender.addStyle(styleUrl);
                            }
                        }
                        if (extendConfig.main) {
                            //如果是还没有加载过的
                            if (!hasProp(_this._cache, key)) {
                                //加载主模块
                                var mainUrl = stringUtils.urlJoin(_this._config.baseUrl, key, extendConfig.main);
                                _this._loadScript({
                                    id: key,
                                    url: mainUrl
                                });
                            } else {
                                var cachedClazz = getOwn(_this._cache, key);
                                _this._deferreds[key].resolve(cachedClazz);
                            }
                        }
                        delete _this._requires[key];
                        break;
                    case EXTEND_MODULE_TYPE.StyleResource:
                        //样式资源
                        if (extendConfig.files && Array.isArray(extendConfig.files)) {
                            extendConfig.files.forEach(function (item) {
                                var styleUrl = stringUtils.urlJoin(_this._config.baseUrl, key, item);
                                if (!ScriptRender.checkStyle(styleUrl)) {
                                    ScriptRender.addStyle(styleUrl);
                                }
                            });
                            _this._deferreds[key].resolve();
                        } else {
                            _this._deferreds[key].reject();
                        }
                        break;
                    case EXTEND_MODULE_TYPE.MaterialResource:
                        //素材资源
                        if (extendConfig.files && Array.isArray(extendConfig.files)) {
                            var realUrls = [];
                            extendConfig.files.forEach(function (item) {
                                realUrls.push(stringUtils.urlJoin(_this._config.baseUrl, key, item));
                            });
                            _this._deferreds[key].resolve(realUrls);
                        } else {
                            _this._deferreds[key].reject();
                        }
                        break;
                }
            });
        }
    }, {
        key: "unload",
        value: function unload(key) {
            var _this2 = this;

            var config = getOwn(this._extendConfig, key);
            if (!config) {
                throw new Error('can not found key in current context');
            }
            switch (config.type) {
                //处理扩展模块
                case EXTEND_MODULE_TYPE.ExtendModule:
                    if (config.style) {
                        var url = stringUtils.urlJoin(this._config.baseUrl, key, config.style);
                        ScriptRender.removeStyle(url);
                    }
                    break;
                //处理样式资源
                case EXTEND_MODULE_TYPE.StyleResource:
                    if (config.files && Array.isArray(extendConfig.files)) {
                        config.files.forEach(function (item) {
                            var url = stringUtils.urlJoin(_this2._config.baseUrl, key, item);
                            ScriptRender.removeStyle(url);
                        });
                    }
                    break;
            }
        }
    }, {
        key: "getDef",
        value: function getDef(key) {
            var own = hasProp(this._deferreds, key);
            if (own) {
                return this._deferreds[key].promise;
            }
            return undefined;
        }
    }, {
        key: "pushQueue",
        value: function pushQueue(key, main, scope) {
            if (_.findIndex(this._queue, ['key', key]) > 0) {
                return;
            }
            this._queue.push({ key: key, main: main, scope: scope });
        }
    }, {
        key: "_makeDef",
        value: function _makeDef(key) {
            //创建延迟对象
            var def = {};
            def.promise = new Promise(function (resolve, reject) {
                def.resolve = resolve;
                def.reject = function (err) {
                    reject(err);
                };
            });
            if (hasProp(this._deferreds, key)) {
                delete this._deferreds[key];
            }
            this._deferreds[key] = def;
        }
    }, {
        key: "_loadScript",
        value: function _loadScript(map) {
            var script = document.createElement('script');
            script.setAttribute('data-extend-module', map.id);
            script.type = 'text/javascript';
            script.charset = 'utf-8';
            script.async = true;
            script.src = map.url;
            script.addEventListener('load', this._onScriptLoaded.bind(this), false);
            script.addEventListener('error', this._onScriptError.bind(this), false);
            document.head.appendChild(script);
        }
    }, {
        key: "_getModuleConfig",
        value: function _getModuleConfig(key) {
            if (this._extendConfig[key]) {
                return jQuery$1.Deferred().resolve({ config: this._extendConfig[key] });
            } else {
                var path = stringUtils.urlJoin(this._config.baseUrl, key, 'package.json');
                return jQuery$1.getJSON(path);
            }
        }
    }, {
        key: "_onScriptError",
        value: function _onScriptError() {}
    }, {
        key: "_onScriptLoaded",
        value: function _onScriptLoaded(e) {
            var key = e.target.dataset.extendModule;
            var main = undefined;
            if (hasProp(this._deferreds, key)) {
                var options = this._extendConfig[key].options || {};
                var fn = _.find(this._queue, ['key', key]);
                if (!fn) {
                    this._deferreds[key].resolve(null);
                } else {
                    main = fn.main.apply(fn.scope || window, [options]);
                    if (!hasProp(this._cache, key)) {
                        //缓存当前的类定义
                        this._cache[key] = { clazz: main, config: options };
                    }
                    this._deferreds[key].resolve(this._cache[key]);
                }
            }
        }
    }, {
        key: "Config",
        get: function get$$1() {
            return this._config;
        }
    }]);
    return ExtendModuleContext;
}();

function hasProp(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
}

function getOwn(obj, prop) {
    return obj && hasProp(obj, prop) && obj[prop];
}

function initAmoeba() {
    mergeToMidware('extendModule', extendModule);
    mergeToMidware('extendModuleRequire', extendModuleRequire);
    mergeToMidware('extendModuleDefine', extendModuleDefine);
    mergeToMidware('extendModuleRelease', extendModuleRelease);
}

var _arguments$1 = arguments;
var _this = window;

var baseReg = /^.*?(?=[^\/]*(\?|$))/;
var absoluteReg = /^(\w+:\/\/|\/)/;
var onlineReg = /^((http|https):\/\/|\/)/;

var urlUtils = {
    getBase: function getBase(url) {
        return url ? baseReg.exec(url)[0] : '';
    },
    isAbsolute: function isAbsolute(url) {
        return absoluteReg.test(url);
    },
    isHttpAddress: function isHttpAddress(url) {
        return onlineReg.test(url);
    },
    resolve: function resolve(base, url) {
        if (_arguments$1.length === 1) {
            url = base;
            base = urlUtils.getBaseLocationUrl();
        }
        return urlUtils.isAbsolute(url) ? url : base + '/' + url;
    },
    getBaseLocationUrl: function getBaseLocationUrl() {
        var url = urlUtils.getBase(location.href);
        urlUtils.getBaseLocationUrl = function () {
            return url;
        };
        return _this.getBaseLocationUrl();
    }
};

var midwareInit = false;

var Midware$1 = {};
var MidwareConfig = {
    BasePath: '', //中间层加载的基础路径
    PlayerReleaseNumber: '000000', //定制播放器的发布号
    ConfigurationPath: 'configuration', //配置文件的路径,相对基础路径
    LanguageBasePath: 'languages', //国际化文件的路径,相对基础路径
    StyleBasePath: 'style', //样式库的路径,相对附件路径
    AssetsBasePath: 'assets', //附件的路径,相对基础路径
    ComponentBasePath: 'js-library', //控件库的路径,相对基础路径
    ExtendBasePath: 'extends', //扩展模块的路径,相对附件路径
    RunEnvironment: 'product' //当前运行环境
};
//定制播放器的配置
var CustomPlayerConfig = {
    Presenters: {},
    Scripts: {}
};

//设置版本号
Object.defineProperty(Midware$1, 'version', { value: "1.5.7" });

Object.defineProperty(Midware$1, 'globalConfig', {
    value: function value(options) {
        if (typeof options.BasePath === 'string') {
            MidwareConfig.BasePath = options.BasePath;
        }
        if (typeof options.LanguageBasePath === 'string') {
            MidwareConfig.LanguageBasePath = options.LanguageBasePath;
        }
        if (typeof options.AssetsBasePath === 'string') {
            MidwareConfig.AssetsBasePath = options.AssetsBasePath;
        }
        if (typeof options.ComponentBasePath === 'string') {
            MidwareConfig.ComponentBasePath = options.ComponentBasePath;
        }
        if (typeof options.PlayerReleaseNumber === 'string') {
            MidwareConfig.PlayerReleaseNumber = options.PlayerReleaseNumber;
        }
        if (typeof options.NativeBridgeClass === 'string') {
            Object.defineProperty(MidwareConfig, 'NativeBridgeClass', { value: options.NativeBridgeClass });
        }
        Object.defineProperty(MidwareConfig, 'Online', { value: urlUtils.isHttpAddress(MidwareConfig.BasePath) });
        if (options.RunEnvironment !== undefined && typeof options.RunEnvironment === 'string') {
            if (options.RunEnvironment === 'product' || options.RunEnvironment === 'development') {
                MidwareConfig.RunEnvironment = options.RunEnvironment;
            }
        }
    }
});

Object.defineProperty(Midware$1, 'startup', {
    value: function value(options) {
        if (midwareInit === true) {
            console.warn("Middleware has been initialized!");
            return;
        }
        midwareInit = true;
        if ((typeof options === "undefined" ? "undefined" : _typeof(options)) !== 'object') {
            console.warn('startup option error');
            return;
        }
        var i18n = jQuery$1.extend({
            configPath: stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.LanguageBasePath),
            configFile: 'language.json',
            load: true
        }, options.i18n),
            courseware = jQuery$1.extend({
            configPath: stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.ConfigurationPath),
            configFile: 'coursesubject.json',
            load: true
        }, options.courseware),
            extend = jQuery$1.extend({ context: "_", load: true }, options.extend),
            style = jQuery$1.extend({
            configPath: stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.AssetsBasePath, MidwareConfig.StyleBasePath),
            configFile: 'style.config.json',
            containVersion: false,
            load: true
        }, options.style),
            abutment = jQuery$1.extend({ load: true }, options.abutment),
            player = jQuery$1.extend({ file: 'config.json' }, options.customPlayer),
            async = options.async === undefined ? true : options.async;
        //加载定制播放器的配置
        getPlayerConfig(MidwareConfig, player.code, player.version, player.file, async).done(function (config) {
            if (config.presenters) {
                for (var key in config.presenters) {
                    var tempConfig = config.presenters[key];
                    CustomPlayerConfig.Presenters[key] = {
                        code: tempConfig.presenterCode,
                        version: tempConfig.version,
                        release: tempConfig.releaseNum
                    };
                }
            }
            if (config.script) {
                for (var i = 0, len = config.script.length; i < len; i++) {
                    var _tempConfig = config.script[i];
                    CustomPlayerConfig.Scripts[_tempConfig.name] = {
                        code: _tempConfig.name,
                        version: _tempConfig.version,
                        release: _tempConfig.releaseNum
                    };
                }
            }
        }).fail(function () {
            console.error("Unable to read the custom player's configuration file");
        });
        //存在i18n的配置
        if (i18n.load) {
            console.info("===Execute multi-language manager to initialization===");
            var configPath = i18n.configPath || MidwareConfig.LanguageBasePath;
            var configFile = i18n.configFile || 'language.json';
            mergeToMidware('i18nManager', i18nManager);
            i18nManager.loadConfig(configPath, configFile, async);
        }
        //存在扩展模块的配置
        if (extend.load) {
            console.info("===Execute the expansion module manager to initialize===");
            var defaultContext = extend.context || "_";
            var baseUrl = stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.AssetsBasePath, MidwareConfig.ExtendBasePath);
            //初始化扩展模块功能
            initAmoeba();
            //进行扩展模块的配置
            Midware$1.extendModule.config({
                context: defaultContext,
                baseUrl: baseUrl
            });
        }
        //存在样式库模块的配置
        if (style.load) {
            console.info("===Execute the style library module manager to initialize===");
            var styleConfigPath = style.configPath || stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.AssetsBasePath, MidwareConfig.StyleBasePath);
            var styleConfigFile = style.configFile || 'style.config.json';
            var containVersion = style.containVersion || false;
            //将StyleManager加入Midware对象中
            mergeToMidware('styleManager', styleManager);
            styleManager.loadConfig(styleConfigPath, styleConfigFile, async, containVersion);
        }
        //加载颗粒配置
        if (courseware.load) {
            console.info("===Load courseware object config===");
            var _configPath = courseware.configPath || MidwareConfig.ConfigurationPath,
                _configFile = courseware.configFile || 'coursesubject.json';
            coursewareConfigManager.loadConfig(_configPath, _configFile, async).done(function () {
                if (courseware.extendConfig) {
                    //需要添加扩展的配置
                    var extendConfig = coursewareConfigManager.get(courseware.extendConfig);
                    if (extendConfig) {
                        Object.defineProperty(MidwareConfig, 'extend', { value: extendConfig });
                    }
                }
            });
        }
        //能力对接层配置
        if (abutment.load) {
            mergeToMidware('wrapManager', wrapManager);
        }
    }
});

function mergeToMidware(name, fn) {
    if (typeof fn === 'function') {
        Object.defineProperty(Midware$1, name, {
            value: fn
        });
    } else {
        if (!Midware$1[name]) {
            Midware$1[name] = fn;
        }
    }
}

var ICPlayerProvider = function () {
    function ICPlayerProvider() {
        classCallCheck(this, ICPlayerProvider);
    }

    createClass(ICPlayerProvider, null, [{
        key: "ConstructorAdapter",


        /**
         * @return {Function}
         */
        value: function ConstructorAdapter() {
            if (window.icCreatePlayer === undefined) {
                return function (target) {};
            }
            return function (target) {
                //定义ICPlayer的事件处理器
                supportFunction.defineProperty(target.prototype, 'onEventReceived', function (name, data) {
                    var _this = this;

                    if (!this.webEvents) {
                        return;
                    }
                    $.each(this.webEvents, function (index, value) {
                        if (value.name === name) {
                            $.each(value.callbacks, function (i, v) {
                                //将数据交给响应对象进行处理
                                v.call(_this, data, name);
                            });
                            return false;
                        }
                    });
                });
                supportFunction.defineProperty(target.prototype, 'webEvents', [], { writable: true });
                supportFunction.defineProperty(target.prototype, 'nativeListener', {}, { writable: true });
                supportFunction.defineProperty(target.prototype, 'nativeBridge', window["Bridge"] ? window["Bridge"] : defaultNativeBridge);
            };
        }

        /**
         * @return {Function}
         */

    }, {
        key: "MethodAdapter",
        value: function MethodAdapter() {
            if (window.icCreatePlayer === undefined) {
                return function (target, key, descriptor) {
                    return descriptor;
                };
            }
            return function (target, key, descriptor) {
                var method = descriptor.value;
                //对方法进行适配
                switch (key) {
                    case "requireComponent":
                        descriptor.value = function () {
                            for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                                args[_key] = arguments[_key];
                            }

                            var adaptedOptions = requireAdapter(args);
                            return method.call(this, adaptedOptions);
                        };
                        break;
                    case "addEventListener":
                        descriptor.value = function () {
                            for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
                                args[_key2] = arguments[_key2];
                            }

                            var name = arguments[0],
                                type = arguments[1],
                                callback = arguments[2];
                            if (callback === null || typeof callback !== 'function') {
                                throw Error('callback is null or not a function');
                            }
                            if (type === ConstVariable$1.PresenterEventType.IC_PLAYER_EVENT) {
                                var hasExists = false;
                                for (var i = 0; i < this.webEvents.length; i++) {
                                    if (this.webEvents[i].name === name) {
                                        this.webEvents[i].callbacks.push(callback);
                                        hasExists = true;
                                        break;
                                    }
                                }
                                if (!hasExists) {
                                    this.webEvents.push({ name: name, callbacks: [callback] });
                                    this._playerController.getEventBus().addEventListener(name, this);
                                }
                            } else if (type === ConstVariable$1.PresenterEventType.NATIVE_EVENT) {
                                var eventKey = this.nativeBridge.registerListener(name, callback, this);
                                this.nativeListener[eventKey] = eventKey;
                            }
                        };
                        break;
                    case "removeEventListener":
                        descriptor.value = function () {
                            var _this2 = this;

                            //移除监听的原生事件
                            if (this.nativeListener) {
                                jQuery$1.each(this.nativeListener, function (name, item) {
                                    _this2.nativeBridge.unRegisterListener(name, item);
                                });
                                this.nativeListener = null;
                            }
                            if (this.webEvents) {
                                //移除监听的Web层事件
                                while (this.webEvents.length > 0) {
                                    this.webEvents.pop();
                                }
                                this.webEvents = null;
                            }
                        };
                        break;
                    case "dispatchEvent":
                        descriptor.value = function () {
                            var name = arguments.length <= 0 ? undefined : arguments[0],
                                type = arguments.length <= 1 ? undefined : arguments[1],
                                data = (arguments.length <= 2 ? undefined : arguments[2]) || {};
                            if (type === ConstVariable$1.PresenterEventType.IC_PLAYER_EVENT) {
                                this.PlayerController.getEventBus().sendEvent(name, data);
                                return true;
                            } else if (type === ConstVariable$1.PresenterEventType.NATIVE_EVENT || type === ConstVariable$1.PresenterEventType.PPT_NATIVE_EVENT) {
                                var bridgeName = "";
                                if (MidwareConfig.NativeBridgeClass !== undefined) {
                                    bridgeName = MidwareConfig.NativeBridgeClass;
                                } else {
                                    //如果是作业系统
                                    if (this.embedApplication("exercise")) {
                                        bridgeName = ConstVariable$1.PresenterBridge.HOMEWORK;
                                    } else {
                                        bridgeName = ConstVariable$1.PresenterBridge.SMART_CLASS;
                                    }
                                }
                                if (type === ConstVariable$1.PresenterEventType.NATIVE_EVENT) {
                                    //APP原生事件类型
                                    return this.nativeBridge.callNative(bridgeName, name, data);
                                } else if (type === ConstVariable$1.PresenterEventType.PPT_NATIVE_EVENT) {
                                    //应用于101PPT的原生事件类型,需要做二次包装
                                    return this.nativeBridge.callNative(bridgeName, 'sendEvent', {
                                        eventName: name,
                                        eventData: data
                                    });
                                }
                            }
                        };
                        break;
                    case "_init":
                        descriptor.value = function () {
                            if (window.player) {
                                var currentRuntime = window.player.getPlayerServices().getRuntime();
                                this._environment.isApp = currentRuntime == window.icCreatePlayer.RUNTIME.STUDENT_MOBILE || currentRuntime == window.icCreatePlayer.RUNTIME.TEACHER_MOBILE;
                                this._environment.isWeb = currentRuntime == window.icCreatePlayer.RUNTIME.WEB;
                                this._environment.isPC = currentRuntime == window.icCreatePlayer.RUNTIME.TEACHER_PC;
                                this._environment.isTeacher = currentRuntime == window.icCreatePlayer.RUNTIME.TEACHER_MOBILE;
                                this._environment.isStudent = currentRuntime == window.icCreatePlayer.RUNTIME.STUDENT_MOBILE;
                            }
                            method.call(this);
                        };
                        break;
                }
                descriptor.writable = descriptor.enumerable = descriptor.configurable = false;
                return descriptor;
            };
        }
    }]);
    return ICPlayerProvider;
}();

function requireAdapter() {
    for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
        args[_key3] = arguments[_key3];
    }

    var name = args[0][0],
        props = args[0][1],
        rendTo = args[0][2],
        layout = args[0][3];
    var id = name;
    //在Properties中查找是否存在'__Id'的字段
    if ((props !== null || props !== undefined) && props.length > 0) {
        props.forEach(function (item) {
            if (item.name === '__Id') {
                id = item.value;
            }
        });
    }
    var adaptedOptions = {
        addonId: name,
        id: id,
        layout: {
            left: 0,
            top: 0,
            width: "100%",
            height: "100%"
        },
        properties: props === null ? [] : props
    };
    if (layout && layout !== null) {
        //合并布局配置
        jQuery$1.extend(adaptedOptions.layout, layout);
        if (layout.zindex !== undefined) {
            adaptedOptions["z-index"] = layout.zindex;
        }
    }
    if (rendTo !== null) {
        jQuery$1.extend(adaptedOptions, { renderTo: rendTo });
    }
    return adaptedOptions;
}

var defaultNativeBridge = {
    registerListener: function registerListener() {
        console.warn("window bridge is null, this message from default bridge");
        return {};
    },
    unRegisterListener: function unRegisterListener() {
        console.warn("window bridge is null, this message from default bridge");
        return {};
    },
    callNative: function callNative() {
        console.warn("window bridge is null, this message from default bridge");
        return {};
    }
};

var MidwayProvider = function () {
    function MidwayProvider() {
        classCallCheck(this, MidwayProvider);
    }

    createClass(MidwayProvider, null, [{
        key: 'ConstructorAdapter',
        value: function ConstructorAdapter() {
            if (window.Midway === undefined) {
                return function (target) {};
            }
            return function (target) {};
        }
    }, {
        key: 'MethodAdapter',
        value: function MethodAdapter() {
            if (window.Midway === undefined) {
                return function (target, key, descriptor) {
                    return descriptor;
                };
            }
            return function (target, key, descriptor) {
                var method = descriptor.value;
                if (key === 'requireComponent') {
                    descriptor.value = function () {
                        for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                            args[_key] = arguments[_key];
                        }

                        var options = requireAdapter$1.call(this, args);
                        return method.call(this, options);
                    };
                } else if (key === 'addEventListener') {
                    descriptor.value = function () {
                        for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
                            args[_key2] = arguments[_key2];
                        }

                        var name = arguments[0],
                            type = arguments[1],
                            callback = arguments[2];
                        var eventType = type;
                        if (type === ConstVariable.PresenterEventType.IC_PLAYER_EVENT) {
                            eventType = 'web_event';
                        }
                        if (callback === null || typeof callback !== 'function') {
                            throw Error('callback is null or not a function');
                        }
                        this.PlayerController.getEventBus().addEventListener(name, eventType, callback, this);
                    };
                } else if (key === 'removeEventListener') {} else if (key === 'dispatchEvent') {
                    descriptor.value = function () {
                        var name = arguments.length <= 0 ? undefined : arguments[0],
                            type = arguments.length <= 1 ? undefined : arguments[1],
                            data = (arguments.length <= 2 ? undefined : arguments[2]) || {};
                        var eventType = type,
                            eventScope = void 0;
                        if (type === ConstVariable.PresenterEventType.IC_PLAYER_EVENT) {
                            eventType = 'web_event';
                        }
                        if (eventType === 'web_event') {
                            eventScope = (arguments.length <= 3 ? undefined : arguments[3]) || 'current_bundle';
                        }
                        this.PlayerController.getEventBus().dispatchEvent(name, eventType, data, eventScope);
                    };
                } else if (key === "_init") {
                    descriptor.value = function () {
                        this._environment.isApp = window.Midway.Settings.Runtime === 'mobile';
                        this._environment.isWeb = window.Midway.Settings.Runtime === 'web';
                        this._environment.isPC = window.Midway.Settings.Runtime === 'pc';
                        this._environment.isTeacher = window.Midway.Terminal === 'teacher';
                        this._environment.isStudent = window.Midway.Terminal === 'student';
                        method.call(this);
                    };
                }
                descriptor.writable = descriptor.enumerable = descriptor.configurable = false;
                return descriptor;
            };
        }
    }]);
    return MidwayProvider;
}();

function requireAdapter$1() {
    for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
        args[_key3] = arguments[_key3];
    }

    var name = args[0][0],
        props = args[0][1],
        rendTo = args[0][2],
        layout = args[0][3];
    var model = {};
    if (Array.prototype.isArray(props) && props.length > 0) {
        props.forEach(function (item) {
            model[item.name] = item.value || (item.text ? JSON.parse(item.text) : undefined);
        });
    }
    var element = undefined;
    if (rendTo !== undefined) {
        if (typeof rendTo === 'string') {
            element = this.View.querySelector(rendTo);
        } else if (rendTo instanceof jQuery) {
            element = rendTo[0];
        } else {
            element = rendTo;
        }
    }
    var extendLayout = $.extend(layout, { style: { width: '100%', height: '100%' } });
    return {
        code: name,
        model: model,
        attributes: extendLayout,
        rendTo: element
    };
}

var _dec;
var _dec2;
var _dec3;
var _dec4;
var _dec5;
var _dec6;
var _dec7;
var _dec8;
var _dec9;
var _dec10;
var _dec11;
var _dec12;
var _class;
var _class2;

function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
    var desc = {};
    Object['ke' + 'ys'](descriptor).forEach(function (key) {
        desc[key] = descriptor[key];
    });
    desc.enumerable = !!desc.enumerable;
    desc.configurable = !!desc.configurable;

    if ('value' in desc || desc.initializer) {
        desc.writable = true;
    }

    desc = decorators.slice().reverse().reduce(function (desc, decorator) {
        return decorator(target, property, desc) || desc;
    }, desc);

    if (context && desc.initializer !== void 0) {
        desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
        desc.initializer = undefined;
    }

    if (desc.initializer === void 0) {
        Object['define' + 'Property'](target, property, desc);
        desc = null;
    }

    return desc;
}

var ModuleBase = (_dec = ICPlayerProvider.ConstructorAdapter(), _dec2 = MidwayProvider.ConstructorAdapter(), _dec3 = ICPlayerProvider.MethodAdapter(), _dec4 = MidwayProvider.MethodAdapter(), _dec5 = ICPlayerProvider.MethodAdapter(), _dec6 = MidwayProvider.MethodAdapter(), _dec7 = ICPlayerProvider.MethodAdapter(), _dec8 = MidwayProvider.MethodAdapter(), _dec9 = ICPlayerProvider.MethodAdapter(), _dec10 = MidwayProvider.MethodAdapter(), _dec11 = ICPlayerProvider.MethodAdapter(), _dec12 = MidwayProvider.MethodAdapter(), _dec(_class = _dec2(_class = (_class2 = function () {
    function ModuleBase() {
        var clazz = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "unknown";
        var interfaceObj = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
        classCallCheck(this, ModuleBase);

        this._basePath = "/";
        this._queryString = {};
        this._playerController = null;
        this._logger = null;
        this._interface = {};
        this._clazz = clazz;
        this._environment = {
            isApp: false,
            isWeb: true,
            isPC: false,
            isTeacher: false,
            isStudent: false
        };
        //模块的视图
        this._view = null;
        //模块的模型
        this._model = null;
        //模块的注入模型
        this._injectModel = null;
        //自定义配置模型
        this._customConfigModel = null;
        this._currentLanguage = 'zh_CN';
        this._app = undefined;
        this.metaInfo = {
            name: "",
            type: ConstVariable$1.PresenterType.FUNCTIONAL
        };
        this._CLASS_ID_ = stringUtils.randomWord(false, 16); //类的唯一ID
        //如果容器注入对象不为空
        if (interfaceObj) {
            jQuery$1.extend(true, this._interface, interfaceObj);
        }
        this._init();
    }

    createClass(ModuleBase, [{
        key: "setPlayerController",
        value: function setPlayerController(controller) {
            assert(controller === undefined, "player controller is null");
            assert(controller.require === undefined, "player controller not contain require method");
            assert(controller.getEventBus === undefined, "player controller not contain getEventBus method");
            this._playerController = controller;
        }
    }, {
        key: "setBasePath",
        value: function setBasePath(path) {
            this._basePath = path !== undefined ? path : "/";
        }
    }, {
        key: "setUrlParams",
        value: function setUrlParams(params) {
            this._queryString = params;
            this._currentLanguage = params["_lang_"] || "zh_CN";
            if (this._queryString["app"]) {
                this._app = this._queryString["app"];
            } else if (this._queryString["sys"]) {
                this._app = this._queryString["sys"];
            }
        }

        /**
         * 模块加载的入口
         */

    }, {
        key: "run",
        value: function run() {
            for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                args[_key] = arguments[_key];
            }

            this._view = args[0][0] || undefined;
            this._model = args[0][1] || undefined;
            this._injectModel = args[0][2] || undefined;
            this._customConfigModel = coursewareConfigManager.get(this.metaInfo.coursewareObject || this.metaInfo.name);
            //在run的时候调用实例化颗粒服务的过程
            this._initModuleService();
        }

        /**
         * 模块销毁时调用的方法
         */

    }, {
        key: "destroy",
        value: function destroy() {
            this.removeEventListener();
            this.$release();
        }

        /**
         * 获取当前模块使用的皮肤
         * @returns {string} 皮肤类型
         */

    }, {
        key: "getSkin",
        value: function getSkin() {
            return 'wood';
        }

        /**
         *
         * @param app
         * @returns {boolean}
         */

    }, {
        key: "embedApplication",
        value: function embedApplication(app) {
            if (this.QueryString) {
                var sysApp = this.QueryString["sys"] !== undefined ? this.QueryString["sys"] : this.QueryString["app"] !== undefined ? this.QueryString["app"] : "unknown";
                return sysApp === app;
            }
            return false;
        }

        /**
         * 添加事件监听器
         * @param name
         * @param type
         * @param callback
         */

    }, {
        key: "addEventListener",
        value: function addEventListener() {
            return -1;
        }

        /**
         * 移除所有事件监听器
         */

    }, {
        key: "removeEventListener",
        value: function removeEventListener() {
            return -1;
        }

        /**
         * 广播一个事件
         * @param name
         * @param type
         * @param data
         * @returns {*}
         */

    }, {
        key: "dispatchEvent",
        value: function dispatchEvent(name, type, data) {
            return -1;
        }

        /**工具类方法**/
        /**
         * 动态加载模块
         * @returns {*|JQueryDeferred<T>}
         */

    }, {
        key: "requireComponent",
        value: function requireComponent() {
            // name, properties, rendTo, layout
            var options = arguments[0],
                deffer = jQuery$1.Deferred();
            this.PlayerController.require(options).done(function (module) {
                if (module._handleOver_) {
                    var pending = [];
                    for (var key in module._handleOver_) {
                        pending.push(module._handleOver_[key]);
                    }
                    jQuery$1.when.apply($, pending).done(function () {
                        deffer.resolve(module);
                    });
                } else {
                    deffer.resolve(module);
                }
            });
            return deffer;
        }

        //创建代理方法

    }, {
        key: "createDelegate",
        value: function createDelegate(fn, args, isAppendArgs, scope, exceptionHandler) {
            return function () {
                //如果创建的时候没有输入参数，使用调用的参数
                var callArgs = args || arguments;
                if (isAppendArgs === true) {
                    //arguments数组化
                    callArgs = Array.prototype.slice.call(arguments, 0);
                    callArgs = callArgs.concat(args);
                }
                try {
                    return fn.apply(scope || window, callArgs);
                } catch (e) {
                    if (jQuery$1.isFunction(exceptionHandler)) {
                        return exceptionHandler(e);
                    } else {
                        throw e;
                    }
                }
            };
        }

        //顺序执行方法

    }, {
        key: "runSequence",
        value: function runSequence(fnConfigs, name) {
            return supportFunction.runSequence(fnConfigs, name);
        }

        /***********/

        //==子类需要重写或实现的方法
        /**
         * 提供给子类生命周期入口方法
         * @param options 加载参数,可变值
         */

    }, {
        key: "$launch",
        value: function $launch(options) {}

        /**
         * 提供给子类生命周期销毁方法
         */

    }, {
        key: "$release",
        value: function $release() {}

        //==子类需要实现的方法结束

        //私有方法开始
        //类初始化方法

    }, {
        key: "_init",
        value: function _init() {
            if (this.metaInfo) {
                this.metaInfo = jQuery$1.extend(this.metaInfo, { _CLASS_ID_: this._CLASS_ID_ });
            } else {
                this.metaInfo = { _CLASS_ID_: this._CLASS_ID_ };
            }
            this._logger = loggerManager().get(this._clazz ? this._clazz : this.metaInfo.name);
            //添加默认日志Handler
            this.Logger.appendHandler(defaultLoggerHandle, { level: LOG_LEVEL.DEBUG });
        }
    }, {
        key: "_trimSlash",
        value: function _trimSlash() {
            var basePath = this.BasePath;
            if (basePath && basePath.length > 1 && basePath[basePath.length - 1] === "/") {
                basePath = basePath.substr(0, basePath.length - 1);
            }
            return basePath;
        }

        //初始化颗粒服务

    }, {
        key: "_initModuleService",
        value: function _initModuleService() {
            //对注入到当前对象中的服务类进行统一的实例化
            if (this.__ModuleServices !== undefined) {
                var me = this;
                jQuery$1.each(this.__ModuleServices, function (key, value) {
                    if (!me[key]) {
                        if (value.hasFilter) {
                            //如果对象是一个函数
                            var clazz = value.filter.call(me);
                            me[key] = clazz != undefined ? new window["__ServiceComponent"][value.namespace][clazz]() : undefined;
                        } else {
                            //如果对象是一个类
                            me[key] = new value.clazz();
                        }
                        if (me[key]["setContext"]) {
                            me[key]["setContext"].call(me[key], me);
                        }
                    }
                });
            }
        }
    }, {
        key: "_loadI18nResource",
        value: function _loadI18nResource(langSet) {
            var _this = this;

            var langDef = jQuery$1.Deferred();
            i18nManager.loadLanguage(this.metaInfo.name, this.Language).done(function (data) {
                i18nManager.replaceView(_this.View, data.lang);
                langSet = data.lang;
                langDef.resolve();
            }).fail(function () {
                console.error("load i18n resource error");
                langDef.reject();
            });
            return langDef.promise();
        }
    }, {
        key: "_loadStyleLibrary",
        value: function _loadStyleLibrary() {
            if (this.metaInfo.type === ConstVariable$1.PresenterType.LAUNCHER) {
                var skin = this.getSkin();
                var styleLib = this.metaInfo.styleLib || this.metaInfo.name;
                styleManager.loadStyle(styleLib, this._app, skin, this.Language);
            }
        }
    }, {
        key: "_releaseStyleLibrary",
        value: function _releaseStyleLibrary() {
            if (this.metaInfo.type === ConstVariable$1.PresenterType.LAUNCHER) {
                styleManager.releaseStyle(this.metaInfo.styleLib || this.metaInfo.name);
            }
        }
    }, {
        key: "MetaInfo",
        get: function get$$1() {
            return this.metaInfo;
        }
    }, {
        key: "Logger",
        get: function get$$1() {
            return this._logger;
        }

        /**
         * @return {string}
         */

    }, {
        key: "BasePath",
        get: function get$$1() {
            return this._basePath;
        }
    }, {
        key: "PlayerController",
        get: function get$$1() {
            return this._playerController;
        }
    }, {
        key: "QueryString",
        get: function get$$1() {
            return this._queryString;
        }
    }, {
        key: "Environment",
        get: function get$$1() {
            return this._environment;
        }
    }, {
        key: "View",
        get: function get$$1() {
            return this._view;
        }
    }, {
        key: "Model",
        get: function get$$1() {
            return this._model;
        }
    }, {
        key: "InjectModel",
        get: function get$$1() {
            return this._injectModel;
        }
    }, {
        key: "CustomConfig",
        get: function get$$1() {
            return this._customConfigModel;
        }
    }, {
        key: "Language",
        get: function get$$1() {
            return this._currentLanguage;
        }
    }]);
    return ModuleBase;
}(), (_applyDecoratedDescriptor(_class2.prototype, "addEventListener", [_dec3, _dec4], Object.getOwnPropertyDescriptor(_class2.prototype, "addEventListener"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "removeEventListener", [_dec5, _dec6], Object.getOwnPropertyDescriptor(_class2.prototype, "removeEventListener"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "dispatchEvent", [_dec7, _dec8], Object.getOwnPropertyDescriptor(_class2.prototype, "dispatchEvent"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "requireComponent", [_dec9, _dec10], Object.getOwnPropertyDescriptor(_class2.prototype, "requireComponent"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_init", [_dec11, _dec12], Object.getOwnPropertyDescriptor(_class2.prototype, "_init"), _class2.prototype)), _class2)) || _class) || _class);


function defaultLoggerHandle(message, context) {
    switch (context.level.name) {
        case 'DEBUG':
            console.debug(message);
            break;
        case 'INFO':
            console.info(message);
            break;
        case 'WARN':
            console.warn(message);
            break;
        case 'ERROR':
            console.error(message);
            break;
        default:
            console.log(message);
            break;
    }
}

var SceneClass = function (_ModuleBase) {
    inherits(SceneClass, _ModuleBase);

    function SceneClass() {
        var clazz = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "unknown";
        var interfaceObj = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
        classCallCheck(this, SceneClass);
        return possibleConstructorReturn(this, (SceneClass.__proto__ || Object.getPrototypeOf(SceneClass)).call(this, clazz, interfaceObj));
    }

    /**
     * 模块加载的入口
     */


    createClass(SceneClass, [{
        key: "run",
        value: function run() {
            var _this2 = this;

            for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                args[_key] = arguments[_key];
            }

            get(SceneClass.prototype.__proto__ || Object.getPrototypeOf(SceneClass.prototype), "run", this).call(this, args);
            //如果当前模块类型为启动器,则需要处理样式库
            get(SceneClass.prototype.__proto__ || Object.getPrototypeOf(SceneClass.prototype), "_loadStyleLibrary", this).call(this);
            var deferred = jQuery$1.Deferred().resolve(),
                langSet = {};
            //加载语言包,场景配置等信息
            return deferred.then(function () {
                //加载多语言信息
                return get(SceneClass.prototype.__proto__ || Object.getPrototypeOf(SceneClass.prototype), "_loadI18nResource", _this2).call(_this2, langSet);
            }).then(function () {
                return sceneManager.getConfig(_this2.metaInfo.name, _this2);
            }).then(function (scene) {
                //当前是启动模块
                return _this2._launcherScene(scene.config);
            }).then(function (data) {
                _this2.Logger.debug({ scene: data.currentScene, lang: langSet });
                return _this2.$launch({ scene: data.currentScene, lang: langSet });
            }).done(function () {
                _this2.Logger.info("module method launch has been run!");
            });
        }
    }, {
        key: "destroy",
        value: function destroy() {
            get(SceneClass.prototype.__proto__ || Object.getPrototypeOf(SceneClass.prototype), "_releaseStyleLibrary", this).call(this);
            get(SceneClass.prototype.__proto__ || Object.getPrototypeOf(SceneClass.prototype), "destroy", this).call(this);
        }

        //==生命周期方法结束==

    }, {
        key: "_launcherScene",
        value: function _launcherScene(sceneConfig) {
            var _this3 = this;

            assert(this.metaInfo.name === undefined, "property name is null in meta info!");
            var deferred = $.Deferred();
            //由子类实现方法,筛选当前场景
            if (sceneConfig.scene && Array.prototype.isArray(sceneConfig.scene)) {
                //如果对当前应用没有配置, 按照default进行匹配, 反之按照已经配置的应用匹配
                var currentScene = sceneConfig.scene.find(function (item) {
                    return item.name === _this3.CurrentApp;
                });
                if (!currentScene && sceneConfig.default) {
                    currentScene = sceneConfig.scene.find(function (item) {
                        return item.name === sceneConfig.default;
                    });
                }
                //如果配置中包含Style
                if (currentScene && currentScene.style) {
                    //动态加载Style对象
                    var url = this._trimSlash() + currentScene.style;
                    //如果是没有加载过的Style对象
                    if (!ScriptRender.checkStyle(url)) {
                        ScriptRender.addStyle(url);
                    }
                }
                //返回当前场景配置
                deferred.resolve({ currentScene: currentScene });
            } else {
                console.error("scene config error!!");
                deferred.resolve({ currentScene: undefined });
            }
            return deferred.promise();
        }
    }, {
        key: "CurrentApp",
        get: function get$$1() {
            return this._app;
        }
    }]);
    return SceneClass;
}(ModuleBase);

var CommonClass = function (_ModuleBase) {
    inherits(CommonClass, _ModuleBase);

    function CommonClass(clazz, interfaceObj) {
        classCallCheck(this, CommonClass);
        return possibleConstructorReturn(this, (CommonClass.__proto__ || Object.getPrototypeOf(CommonClass)).call(this, clazz, interfaceObj));
    }

    /**
     * 模块加载的入口
     */


    createClass(CommonClass, [{
        key: "run",
        value: function run() {
            var _this2 = this;

            for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                args[_key] = arguments[_key];
            }

            get(CommonClass.prototype.__proto__ || Object.getPrototypeOf(CommonClass.prototype), "run", this).call(this, args);
            //处理样式库
            get(CommonClass.prototype.__proto__ || Object.getPrototypeOf(CommonClass.prototype), "_loadStyleLibrary", this).call(this);
            var deferred = jQuery$1.Deferred().resolve(),
                langSet = {};
            return deferred.then(function () {
                //加载多语言信息
                return get(CommonClass.prototype.__proto__ || Object.getPrototypeOf(CommonClass.prototype), "_loadI18nResource", _this2).call(_this2, langSet);
            }).then(function () {
                return _this2.$launch({ lang: langSet });
            }).done(function () {
                _this2.Logger.info("launch presenter complete!");
            });
        }
    }, {
        key: "destroy",
        value: function destroy() {
            get(CommonClass.prototype.__proto__ || Object.getPrototypeOf(CommonClass.prototype), "_releaseStyleLibrary", this).call(this);
            get(CommonClass.prototype.__proto__ || Object.getPrototypeOf(CommonClass.prototype), "destroy", this).call(this);
        }
    }, {
        key: "setModuleSkin",
        value: function setModuleSkin(skin) {
            if (this.metaInfo.type === ConstVariable$1.PresenterType.LAUNCHER) {
                if (window.Midware.styleManager) {
                    Midware.styleManager.changeStyle(this.metaInfo.name, this._app, skin, this.Language);
                }
            }
        }
    }, {
        key: "ComponentLoader",
        get: function get$$1() {
            if (this.metaInfo.type !== ConstVariable$1.PresenterType.LAUNCHER || !this.loader) {
                throw new Error('current module is not Launcher!!');
            }
            return this.loader;
        }
    }]);
    return CommonClass;
}(ModuleBase);

var defaultControlService = function defaultControlService() {
    var service = function service() {};
    /**
     * 定义模块服务对象是否被控制器所托管, 此方法相对服务对象接口定义具备更高优先级
     * @param metaInfo 模块元数据
     * @param service 模块服务对象
     * @returns {boolean} 是否被拓宽
     */
    service.prototype.isUnderControl = function (metaInfo, service) {
        console.log("default control service");
        return false;
    };
    /**
     * 模块生命周期方法run执行前
     * @param interfaceName 接口名称
     * @param metaInfo 模块服务对象
     * @param service 模块服务对象
     */
    service.prototype.beforePresenterRun = function (interfaceName, metaInfo, service) {
        console.log("default control service");
    };
    /**
     * 模块生命周期方法run执行后
     * @param interfaceName 接口名称
     * @param metaInfo 模块服务对象
     * @param service 模块服务对象
     */
    service.prototype.afterPresenterRun = function (interfaceName, metaInfo, service) {
        console.log("default control service");
    };
    /**
     * 互动习题布局模块被设置之后
     * @param service 布局模块服务对象
     */
    service.prototype.afterSetLayoutService = function (service) {
        console.log("default control service");
    };
    /**
     * 定义控制器需要托管的模块服务类型, 以接口方法列表形式提供;
     * 当模块服务实现所有方法时, 该模块服务将被控制器所托管
     * @returns {Array} 控制器可管理模块服务接口对象
     * @example 返回对象定义 [{"name": "接口名称", "methods": [string array, 接口方法列表]}, {...}]
     */
    service.prototype.getInterfaceMethods = function () {
        console.log("default control service");
        return [];
    };

    return new service();
};

var CUSTOM_NAMESPACE = "__Custom";

var CommonController = function (_CommonClass) {
    inherits(CommonController, _CommonClass);

    function CommonController() {
        var clazz = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'undefined';
        var interfaceObj = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
        classCallCheck(this, CommonController);

        var _this = possibleConstructorReturn(this, (CommonController.__proto__ || Object.getPrototypeOf(CommonController)).call(this, clazz, interfaceObj));

        _this.metaInfo.type = ConstVariable$1.PresenterType.CONTROLLER;
        _this._controlService = defaultControlService();
        //设置初始的Interface对象
        _this._interface.processBeforeRun = _this.processBeforeRun.bind(_this);
        _this._interface.processAfterRun = _this.processAfterRun.bind(_this);
        //控制服务列表
        _this._serviceList = {};
        _this._loadDeffers = {};
        _this._layoutService = null;
        _this._interceptPresenter = [];
        //是否只注入一次
        _this._interceptOnce = true;
        return _this;
    }

    createClass(CommonController, [{
        key: "processBeforeRun",


        //对容器实现的接口方法,在每个模块被加载前会先运行该方法
        value: function processBeforeRun() {
            var _this2 = this;

            var presenter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { getService: null, metaInfo: null };

            if (presenter.getService && presenter.metaInfo && typeof presenter.getService === "function") {
                var metaInfo = presenter.metaInfo,
                    service = presenter.getService();
                if (service !== undefined && service['then']) {
                    var identify = metaInfo.name + '@' + metaInfo._CLASS_ID_;
                    if (this._loadDeffers[identify] === undefined) {
                        this._loadDeffers[identify] = $.Deferred();
                    }
                    service.then(function () {
                        _this2._processService(metaInfo, presenter._service_);
                        if (_this2._loadDeffers[identify] && _this2._loadDeffers[identify].state() === "pending") {
                            _this2._loadDeffers[identify].resolve();
                        }
                    });
                } else {
                    this._processService(metaInfo, service);
                }

                //如果Presenter是功能组件
                if (metaInfo.type === ConstVariable$1.PresenterType.FUNCTIONAL) {
                    var _identify = metaInfo.name + '@' + metaInfo._CLASS_ID_,
                        tKey = this.metaInfo.name + "-" + _identify;
                    presenter._handleOver_ = presenter._handleOver_ || {};
                    presenter._handleOver_[tKey] = presenter._handleOver_[tKey] || $.Deferred();
                }
            }
        }
    }, {
        key: "processAfterRun",
        value: function processAfterRun() {
            var _this3 = this;

            var presenter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { getService: null, metaInfo: null, _handleOver_: null };

            if (presenter.getService && presenter.metaInfo && typeof presenter.getService === "function") {
                var metaInfo = presenter.metaInfo,
                    classIdentify = metaInfo.name + '@' + metaInfo._CLASS_ID_;
                if (this._loadDeffers[classIdentify]) {
                    this._loadDeffers[classIdentify].then(function () {
                        _this3._processServiceAfter(metaInfo, classIdentify);
                        if (metaInfo.type === ConstVariable$1.PresenterType.FUNCTIONAL && presenter._handleOver_) {
                            presenter._handleOver_[_this3.metaInfo.name + "-" + classIdentify].resolve();
                        }
                    });
                } else {
                    this._processServiceAfter(metaInfo, classIdentify);
                    if (metaInfo.type === ConstVariable$1.PresenterType.FUNCTIONAL && presenter._handleOver_) {
                        presenter._handleOver_[this.metaInfo.name + "-" + classIdentify].resolve();
                    }
                }
            }
        }
    }, {
        key: "_discoverInterface",
        value: function _discoverInterface(identify) {
            var setting = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { interface: "", methods: [] };
            var metaInfo = arguments[2];
            var service = arguments[3];

            var isImplement = true;
            if (setting.methods.length === 0) {
                isImplement = false;
            } else {
                $.each(setting.methods, function (k, v) {
                    if (service[v] === undefined) {
                        isImplement = false;
                        return false;
                    }
                });
            }
            //如果接口有实现
            if (isImplement) {
                var exists = false;
                //检查是否已经添加过了
                $.each(this._serviceList[identify], function (k, v) {
                    if (v.metaInfo.name === metaInfo.name && v.metaInfo._CLASS_ID_ === metaInfo._CLASS_ID_) {
                        exists = true;
                        return false;
                    }
                });
                if (!exists) {
                    this._serviceList[identify].push({ metaInfo: metaInfo, service: service });
                    this.ControlService.beforePresenterRun(setting.name, metaInfo, service);
                }
            }
        }
    }, {
        key: "_processService",
        value: function _processService() {
            var _this4 = this;

            var metaInfo = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { name: null, type: null };
            var service = arguments[1];

            if (metaInfo.type === ConstVariable$1.PresenterType.LAYOUT && this._layoutService === null) {
                //如果是布局组件,做特殊处理; 为控制模块对象默认添加布局服务属性, 并执行afterSetLayoutService方法
                this._layoutService = service;
                this._controlService.afterSetLayoutService(service);
            }
            var interfaces = this._controlService.getInterfaceMethods();
            if (Array.isArray(interfaces) && interfaces.length > 0) {
                $.each(interfaces, function (key, setting) {
                    var identify = setting.name + '@' + metaInfo._CLASS_ID_;
                    if (!_this4._serviceList[identify]) {
                        _this4._serviceList[identify] = [];
                    }
                    _this4._discoverInterface(identify, setting, metaInfo, service);
                });
            }
            //继续判断当前传入的Service对象是否服务控制对象自定义的控制条件
            if (this._controlService.isUnderControl(metaInfo, service)) {
                this._serviceList[CUSTOM_NAMESPACE] = this._serviceList["__Custom"] || [];
                var exists = false;
                $.each(this._serviceList[CUSTOM_NAMESPACE], function (k, v) {
                    if (v.metaInfo.name === metaInfo.name) {
                        exists = true;
                        return false;
                    }
                });
                if (!exists) {
                    this._serviceList[CUSTOM_NAMESPACE].push({ metaInfo: metaInfo, service: service });
                    //执行控制类方法
                    this._controlService.beforePresenterRun(CUSTOM_NAMESPACE, metaInfo, service);
                }
            }
        }
    }, {
        key: "_processServiceAfter",
        value: function _processServiceAfter(metaInfo, identify) {
            if ($.inArray(identify, this._interceptPresenter) >= 0) {
                if (this.InterceptOnce) {
                    return;
                }
            } else {
                this._interceptPresenter.push(identify);
            }

            var self = this;
            $.each(this._serviceList, function (name, list) {
                var temp = name.split('@'),
                    interfaceName = temp[0],
                    classId = temp[1];
                $.each(list, function (i, s) {
                    if (s.metaInfo.name + '@' + s.metaInfo._CLASS_ID_ === metaInfo.name + '@' + metaInfo._CLASS_ID_) {
                        self._controlService.afterPresenterRun(interfaceName, s.metaInfo, s.service);
                    }
                });
            });
        }
    }, {
        key: "InterceptOnce",
        get: function get$$1() {
            return this._interceptOnce;
        },
        set: function set$$1(value) {
            if (typeof value === "boolean") {
                this._interceptOnce = value;
            }
        }
    }, {
        key: "ControlService",
        get: function get$$1() {
            return this._controlService;
        },
        set: function set$$1(service) {
            //设置控制服务对象
            $.extend(this._controlService, service);
        }
    }, {
        key: "__interface",
        get: function get$$1() {
            return this._interface;
        }
    }, {
        key: "LayoutService",
        get: function get$$1() {
            return this._layoutService;
        }
    }]);
    return CommonController;
}(CommonClass);

var componentContext = {};
var moduleInstance = {};
var injectModels = {};
var namespaceQueue = [];
var deferreds = {};
var waitting = {};
var namespaceVersion = {};
/*组件配置*/
var componentConfig = function componentConfig(settings) {
    //在线场景才需要,离线场景目录是固定的
    if (MidwareConfig.Online) {
        if (!settings && (typeof settings === "undefined" ? "undefined" : _typeof(settings)) === 'object') {
            //可传入配置
            jQuery$1.extend(true, namespaceVersion, settings);
        } else {
            //从config中获取
            for (var key in CustomPlayerConfig.Presenters) {
                var temp = CustomPlayerConfig.Presenters[key];
                if (temp.code.indexOf('component-') === 0) {
                    var ns = temp.code.substring(10);
                    if (!supportFunction.hasProp(namespaceVersion, ns)) {
                        namespaceVersion[ns] = temp.version;
                    }
                }
            }
        }
    }
    return jQuery$1.Deferred().resolve();
};
/*组件定义*/
var componentDefine = function componentDefine(key, deps, main) {
    var keyInfo = normalizeComponentName(key);
    var dependKeyInfo = [];
    if (typeof deps === 'function' && main === undefined) {
        main = deps;
    }
    var options = {
        depends: [],
        visibility: "public"
    };
    if ((typeof deps === "undefined" ? "undefined" : _typeof(deps)) === 'object' && typeof main === 'function') {
        if (Array.prototype.isArray(deps)) {
            //如果是数组
            options.depends = deps;
        } else {
            //如果是对象
            options.visibility = supportFunction.hasProp(deps, 'visibility') ? supportFunction.getOwn(deps, 'visibility') : 'public';
            options.depends = supportFunction.hasProp(deps, 'depends') ? supportFunction.getOwn(deps, 'depends') : [];
        }
    }
    //如果当前ns没有被加载过
    if (!supportFunction.hasProp(componentContext, keyInfo.ns)) {
        namespaceQueue.push({ ns: keyInfo.ns, loaded: false });
        //实例化ns对应的上下文对象
        componentContext[keyInfo.ns] = new ComponentContext(keyInfo);
    }
    options.depends.forEach(function (item) {
        var temp = normalizeComponentName(item);
        //如果依赖的ns没有被加载过
        if (namespaceQueue.findIndex(function (item) {
            return item.ns === temp.ns;
        }) === -1) {
            namespaceQueue.push({ ns: temp.ns, loaded: false });
        }
        if (!supportFunction.hasProp(componentContext, temp.ns)) {
            componentContext[temp.ns] = new ComponentContext(temp);
        }
        dependKeyInfo.push(temp);
    });
    componentContext[keyInfo.ns].push(keyInfo.key, dependKeyInfo, main, options);
};
/*组件请求*/
var componentRequire = function componentRequire(key) {
    var loadKeys = [],
        requireType = 'component';
    if (typeof key === 'string') {
        //请求单个组件
        var keyInfo = normalizeComponentName(key);
        loadKeys.push(keyInfo);
    } else if ((typeof key === "undefined" ? "undefined" : _typeof(key)) === 'object' && Array.prototype.isArray(key)) {
        requireType = 'load';
        //请求多个复数组件
        key.forEach(function (item) {
            var keyInfo = normalizeComponentName(item);
            if (loadKeys.findIndex(function (item) {
                return item.ns === keyInfo.ns && item.key === keyInfo.key;
            }) === -1) {
                //避免组件被重复请求
                loadKeys.push(keyInfo);
            }
        });
    }

    var promises = [];
    loadKeys.forEach(function (ki) {
        if (!supportFunction.hasProp(componentContext, ki.ns) && !supportFunction.hasProp(waitting, ki.ns)) {
            namespaceQueue.push({ ns: ki.ns, loaded: false });
            //实例化ns对应的上下文对象, 并开始加载
            componentContext[ki.ns] = new ComponentContext(ki);
            componentContext[ki.ns].config();
        }
        //将当前命名空间的延迟对象加入队列
        promises.push(getDefer(ki.ns).promise);
    });
    if (requireType === 'component') {
        //当个异步组件请求
        return function () {
            return Promise.all(promises).then(function () {
                delete waitting[loadKeys[0].ns];
                //所有的延迟对象都resolve
                return componentContext[loadKeys[0].ns].load(loadKeys[0].key);
            });
        };
    } else {
        //多个异步组件请求
        return Promise.all(promises).then(function () {
            var components = {};
            loadKeys.forEach(function (loadKey) {
                delete waitting[loadKey.ns];
                components[loadKey.ns + ':' + loadKey.key] = componentContext[loadKey.ns].load(loadKey.key);
            });
            return components;
        });
    }
};

var ComponentContext = function () {
    function ComponentContext(keyInfo) {
        classCallCheck(this, ComponentContext);

        this._components = {};
        this._classes = {};
        this._as = keyInfo.as;
        this._ns = keyInfo.ns;
        this._hasBeenLoaded = false;

        if (this._as) {
            var temp = this._ns.split('.');
            this._nsPath = temp[0];
        }
    }

    createClass(ComponentContext, [{
        key: "push",
        value: function push(key, depends, main, options) {
            if (!supportFunction.hasProp(this._components, key)) {
                this._components[key] = { depends: depends, main: main, visibility: options.visibility };
            }
        }
    }, {
        key: "config",
        value: function config() {
            if (this._hasBeenLoaded) {
                console.warn("this component namespace has been loaded!");
                return;
            }
            var fileName = (this._as || this._ns).toLowerCase() + '.dist.js';
            //如果是开发的环境, 加载组件库时需要添加dist路径
            var version = supportFunction.getOwn(namespaceVersion, this._ns) || (MidwareConfig.RunEnvironment === 'development' ? "dist" : "");
            var nsPath = void 0;
            if (MidwareConfig.BasePath === '') {
                nsPath = stringUtils.urlJoin(MidwareConfig.ComponentBasePath, 'component-' + (this._nsPath || this._ns), version, fileName);
            } else {
                nsPath = stringUtils.urlJoin(MidwareConfig.BasePath, MidwareConfig.ComponentBasePath, 'component-' + (this._nsPath || this._ns), version, fileName);
            }
            var defer = getDefer(this._ns);
            this._loadScript({ id: this._ns, url: nsPath });
            return defer.promise;
        }

        /**
         * 加载当前命名空间下, 指定键值的组件
         * @param key 组件的键值
         */

    }, {
        key: "load",
        value: function load(key) {
            var _this = this;

            if (!supportFunction.hasProp(this._components, key)) {
                throw new Error('the namespace ' + this._ns + ' not contain component names ' + key);
            }
            var config = this._components[key],
                refs = [];
            //如果请求的组件是私有组件
            if (config.visibility === 'private') {
                throw Error('The component ' + key + ' is not available for private components');
            }
            if (config.depends && Array.prototype.isArray(config.depends)) {
                //如果存在依赖组件
                config.depends.forEach(function (item) {
                    //依赖当前命名空间
                    if (item.ns === _this._ns) {
                        _this.get(item.key, refs);
                    } else {
                        getComponent(item.ns, item.key, refs);
                    }
                });
            }
            return config.main.apply(window, refs);
        }
    }, {
        key: "get",
        value: function get$$1(key, refs) {
            var _this2 = this;

            if (supportFunction.hasProp(this._classes, key)) {
                refs.push(this._classes[key]);
            } else {
                var config = this._components[key];
                var tmpRefs = [];
                if (config.depends && config.depends.length > 0) {
                    config.depends.forEach(function (item) {
                        if (item.ns === _this2._ns) {
                            _this2.get(item.key, tmpRefs);
                        } else {
                            getComponent(item.ns, item.key, tmpRefs);
                        }
                    });
                }
                var clazz = config.main.apply(window, tmpRefs);
                this._classes[key] = clazz;
                refs.push(clazz);
            }
        }

        /**
         * 获取指定组件的配置
         * @param key 组件名称
         */

    }, {
        key: "getConfig",
        value: function getConfig(key) {
            return supportFunction.getOwn(this._components, key);
        }
    }, {
        key: "_loadScript",
        value: function _loadScript(map) {
            if (waitting[map.id]) {
                return;
            }
            waitting[map.id] = true;
            var script = document.createElement('script');
            script.setAttribute('data-extend-module', map.id);
            script.type = 'text/javascript';
            script.charset = 'utf-8';
            script.async = true;
            script.src = map.url;
            script.addEventListener('load', this._onScriptLoaded.bind(this), false);
            script.addEventListener('error', this._onScriptError.bind(this), false);
            document.head.appendChild(script);
        }

        //当前组件包完成加载

    }, {
        key: "_onScriptLoaded",
        value: function _onScriptLoaded() {
            var _this3 = this;

            var temp = namespaceQueue.find(function (item) {
                return item.ns === _this3._ns;
            });
            temp.loaded = true;

            var next = namespaceQueue.find(function (item) {
                return item.loaded === false;
            });
            if (next) {
                //如果还存在需要加载的依赖组件包
                waitForDepend(next.ns, getDefer(this._ns));
            } else {
                //以没有需要在加载的对象了
                getDefer(this._ns).resolve();
            }
        }
    }, {
        key: "_onScriptError",
        value: function _onScriptError() {
            getDefer(this._ns).reject();
        }
    }, {
        key: "PackageLoaded",
        get: function get$$1() {
            return this._hasBeenLoaded;
        },
        set: function set$$1(value) {
            this._hasBeenLoaded = value;
        }
    }]);
    return ComponentContext;
}();

function normalizeComponentName(name) {
    if (typeof name !== "string" || name.indexOf(':') < 0) {
        throw new Error("invalid component name");
    }
    var temp = name.split(':');
    if (temp.length !== 2) {
        throw new Error('the component name only contain namespace and names');
    }
    //如果NS中包含'.'
    if (temp[0].indexOf('.') > 0) {
        var temp2 = temp[0].split('.');
        if (temp2.length !== 2) {
            throw new Error('the component namespace only contain one dot');
        }
        //返回内容包含命名空间, 控件集, 控件名称
        return { ns: temp[0], as: temp2[1], key: temp[1] };
    }
    //返回内容包含命名空间, 控件名称
    return { ns: temp[0], key: temp[1] };
}

function callDepend(ns, defer) {
    if (!supportFunction.hasProp(componentContext, ns)) {
        throw Error('component context not exists!');
    }
    if (!componentContext[ns].PackageLoaded) {
        //如果还没有加载过
        return componentContext[ns].config();
    } else {
        //如果已经加载过
        var nextNs = namespaceQueue.shift();
        if (nextNs) {
            callDepend(nextNs);
        } else {
            componentContext[ns].load();
        }
    }
}

function waitForDepend(ns, defer) {
    if (waitting[ns]) {
        var def = getDefer(ns),
            finishPromise = def.finishPromise;
        def.finishPromise = function () {
            finishPromise();
            defer.resolve();
        };
    }
    defer.dependCount += 1;
    callDepend(ns).then(function () {
        defer.dependCount -= 1;
        defer.finishPromise();
        defer.resolve();
    });
}

function makeDefer(ns) {
    if (supportFunction.hasProp(deferreds, ns)) {
        throw new Error('def has exists');
    }

    var defer = {};
    defer.promise = new Promise(function (resolve, reject) {
        defer.resolve = resolve;
        defer.reject = reject;
        defer.finishPromise = function () {
            defer.dependCount -= 1;
            componentContext[ns].PackageLoaded = true;
        };
    });
    defer.namespace = ns;
    defer.dependCount = 0;
    return defer;
}

function getDefer(ns) {
    var defer = void 0;
    if (ns) {
        defer = supportFunction.hasProp(deferreds, ns) && deferreds[ns];
        if (!defer) {
            defer = deferreds[ns] = makeDefer(ns);
        }
    }
    return defer;
}

function getComponent(ns, key, refs) {
    if (!supportFunction.hasProp(componentContext, ns)) {
        throw new Error('the namespace ' + ns + ' not loaded!');
    }
    var config = componentContext[ns].getConfig(key);
    if (!config) {
        throw Error('The component does not exist in the specified namespace');
    }
    if (config.visibility === 'private') {
        throw Error('The component ' + key + ' is not available for private components');
    }
    return componentContext[ns].get(key, refs);
}

/**
 * 定义被管理的组件的方法
 */
function ManagedComponent(options) {
    var doBeforeRun = undefined,
        doBeforeDestroy = undefined,
        injectModel = undefined;
    if (options && typeof options.beforeRun === 'function') {
        doBeforeRun = options.beforeRun;
    }
    if (options && typeof options.beforeDestroy === 'function') {
        doBeforeDestroy = options.beforeDestroy;
    }
    if (options && options.injectModel) {
        injectModel = options.injectModel;
    }
    return function (target) {
        Object.defineProperty(target.prototype, 'beforeDestroy', {
            configurable: false,
            enumerable: true,
            writable: false,
            value: function value() {
                removeModuleInstance(this.metaInfo.name, this._CLASS_ID_);
                if (doBeforeDestroy) {
                    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                        args[_key] = arguments[_key];
                    }

                    doBeforeDestroy.apply(this, args);
                }
            }
        });
        Object.defineProperty(target.prototype, "beforeRun", {
            configurable: false,
            enumerable: true,
            writable: false,
            value: function value() {
                pushModuleInstance(this.metaInfo.name, this._CLASS_ID_, this);
                if (doBeforeRun) {
                    for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
                        args[_key2] = arguments[_key2];
                    }

                    doBeforeRun.apply(this, args);
                }
            }
        });
        //执行beforeRun方法
        if (typeof target.prototype.run === 'function') {
            var doRun = target.prototype.run;
            target.prototype.run = function () {
                //处理外部注入的模型
                if (this.QueryString && this.QueryString['app']) {
                    var app = this.QueryString['app'];
                    if (injectModels[app] && injectModels[app][this.metaInfo.name]) {
                        injectModel = !injectModel ? injectModels[app][this.metaInfo.name] : $.extend(true, injectModel, injectModels[app][this.metaInfo.name]);
                    }
                }
                //在执行基类Run方法执行时注入额外的对象

                for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
                    args[_key3] = arguments[_key3];
                }

                args.push(injectModel);
                //执行运行前的方法
                target.prototype.beforeRun.apply(this, args);
                //执行Run方法
                return doRun.apply(this, args);
            };
        }
        //执行beforeDestroy方法
        if (typeof target.prototype.destroy === 'function') {
            var doDestroy = target.prototype.destroy;
            target.prototype.destroy = function () {
                for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
                    args[_key4] = arguments[_key4];
                }

                target.prototype.beforeDestroy.apply(this, args);
                return doDestroy.apply(this.args);
            };
        }
    };
}

function pushModuleInstance(key, id, instance) {
    if (!supportFunction.hasProp(moduleInstance, key)) {
        moduleInstance[key] = {};
    }
    if (!supportFunction.hasProp(moduleInstance[key], id)) {
        moduleInstance[key][id] = instance;
    }
}

function removeModuleInstance(key, id) {
    if (supportFunction.hasProp(moduleInstance, key) && supportFunction.hasProp(moduleInstance[key], id)) {
        delete moduleInstance[key][id];
    }
    if (supportFunction.isEmptyObject(moduleInstance[key])) {
        delete moduleInstance[key];
    }
}

/**定义对外暴露的全局变量**/
function initSwarm() {
    mergeToMidware('injectModel', function (app, key, model) {
        if (!supportFunction.hasProp(injectModels, app)) {
            injectModels[app] = {};
        }
        if (model) {
            injectModels[app][key] = model;
        }
    });
    mergeToMidware('componentDefine', componentDefine);
    mergeToMidware('componentRequire', componentRequire);
    mergeToMidware('componentConfig', componentConfig);
    mergeToMidware('ManagedComponent', ManagedComponent);
}

function stringPolyFill() {
    String.prototype.trim = function (char, type) {
        if (char) {
            if (type === 'left') {
                return this.replace(new RegExp('^\\' + char + '+', 'g'), '');
            } else if (type === 'right') {
                return this.replace(new RegExp('\\' + char + '+$', 'g'), '');
            }
            return this.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
        }
        return this.replace(/^\s+|\s+$/g, '');
    };
    if (typeof String.prototype.insert !== 'function') {
        String.prototype.insert = function (index, string) {
            if (index > 0) return this.substring(0, index) + string + this.substring(index, this.length);else return string + this;
        };
    }
}

function typescriptPolyFill() {
    //TypeScript poly fill
    if (!self.__extends) {
        self.__extends = function (d, b) {
            for (var p in b) {
                if (b.hasOwnProperty(p)) d[p] = b[p];
            }function __() {
                this.constructor = d;
            }

            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    }

    if (!self.__decorate) {
        self.__decorate = function (decorators, target, key, desc) {
            var c = arguments.length,
                r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
                d = void 0;
            if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect['decorate'] === "function") r = Reflect['decorate'](decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) {
                if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            }return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
    }

    if (!self.__assign) {
        self.__assign = function (t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
                s = arguments[i];
                for (var p in s) {
                    if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
                }
            }
            return t;
        };
    }

    if (!self.__awaiter) {
        self.__awaiter = function (thisArg, _arguments, P, generator) {
            return new (P || (P = Promise))(function (resolve, reject) {
                function fulfilled(value) {
                    try {
                        step(generator.next(value));
                    } catch (e) {
                        reject(e);
                    }
                }

                function rejected(value) {
                    try {
                        step(generator["throw"](value));
                    } catch (e) {
                        reject(e);
                    }
                }

                function step(result) {
                    result.done ? resolve(result.value) : new P(function (resolve) {
                        resolve(result.value);
                    }).then(fulfilled, rejected);
                }

                step((generator = generator.apply(thisArg, _arguments)).next());
            });
        };
    }

    if (!self.__generator) {
        self.__generator = function (thisArg, body) {
            var _ = {
                label: 0, sent: function sent() {
                    if (t[0] & 1) throw t[1];
                    return t[1];
                }, trys: [], ops: []
            },
                f = void 0,
                y = void 0,
                t = void 0;
            return { next: verb(0), "throw": verb(1), "return": verb(2) };
            function verb(n) {
                return function (v) {
                    return step([n, v]);
                };
            }

            function step(op) {
                if (f) throw new TypeError("Generator is already executing.");
                while (_) {
                    try {
                        if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
                        if (y = 0, t) op = [0, t.value];
                        switch (op[0]) {
                            case 0:
                            case 1:
                                t = op;
                                break;
                            case 4:
                                _.label++;
                                return { value: op[1], done: false };
                            case 5:
                                _.label++;
                                y = op[1];
                                op = [0];
                                continue;
                            case 7:
                                op = _.ops.pop();
                                _.trys.pop();
                                continue;
                            default:
                                if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                                    _ = 0;
                                    continue;
                                }
                                if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
                                    _.label = op[1];
                                    break;
                                }
                                if (op[0] === 6 && _.label < t[1]) {
                                    _.label = t[1];
                                    t = op;
                                    break;
                                }
                                if (t && _.label < t[2]) {
                                    _.label = t[2];
                                    _.ops.push(op);
                                    break;
                                }
                                if (t[2]) _.ops.pop();
                                _.trys.pop();
                                continue;
                        }
                        op = body.call(thisArg, _);
                    } catch (e) {
                        op = [6, e];
                        y = 0;
                    } finally {
                        f = t = 0;
                    }
                }if (op[0] & 5) throw op[1];
                return { value: op[0] ? op[1] : void 0, done: true };
            }
        };
    }
}

function arrayPolyFill() {
    if (typeof Array.prototype.from !== 'function') {
        Array.prototype.from = function () {
            var toStr = Object.prototype.toString;
            var isCallable = function isCallable(fn) {
                return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
            };
            var toInteger = function toInteger(value) {
                var number = Number(value);
                if (isNaN(number)) {
                    return 0;
                }
                if (number === 0 || !isFinite(number)) {
                    return number;
                }
                return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
            };
            var maxSafeInteger = Math.pow(2, 53) - 1;
            var toLength = function toLength(value) {
                var len = toInteger(value);
                return Math.min(Math.max(len, 0), maxSafeInteger);
            };
            return function from(arrayLike /*, mapFn, thisArg */) {
                var C = this;
                var items = Object(arrayLike);
                if (arrayLike === null) {
                    throw new TypeError('Array.from requires an array-like object - not null or undefined');
                }
                var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
                var T = void 0;
                if (typeof mapFn !== 'undefined') {
                    if (!isCallable(mapFn)) {
                        throw new TypeError('Array.from: when provided, the second argument must be a function');
                    }
                    if (arguments.length > 2) {
                        T = arguments[2];
                    }
                }
                var len = toLength(items.length),
                    A = isCallable(C) ? Object(new C(len)) : new Array(len),
                    k = 0,
                    kValue = void 0;
                while (k < len) {
                    kValue = items[k];
                    if (mapFn) {
                        A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
                    } else {
                        A[k] = kValue;
                    }
                    k += 1;
                }
                A.length = len;
                return A;
            };
        }();
    }

    if (typeof Array.prototype.forEach !== 'function') {
        Array.prototype.forEach = function (callback, thisObj) {
            var T = void 0,
                k = void 0;
            if (this === null) {
                throw new TypeError(' this is null or not defined');
            }
            var O = Object(this),
                len = O.length >>> 0;
            if (typeof callback !== "function") {
                throw new TypeError(callback + ' is not a function');
            }
            if (arguments.length > 1) {
                T = thisObj;
            }
            k = 0;
            while (k < len) {
                var kValue = void 0;
                if (k in O) {
                    kValue = O[k];
                    callback.call(T, kValue, k, O);
                }
                k++;
            }
        };
    }
    //修正NodeList
    if (typeof NodeList.prototype.forEach !== 'function') {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }

    if (typeof Array.prototype.each !== 'function') {
        Array.prototype.each = function (callback, thisObj) {
            var T = void 0,
                k = void 0;

            if (this === null) {
                throw new TypeError(' this is null or not defined');
            }
            var O = Object(this),
                len = O.length >>> 0;
            if (typeof callback !== "function") {
                throw new TypeError(callback + ' is not a function');
            }
            if (arguments.length > 1) {
                T = thisObj;
            }
            k = 0;
            while (k < len) {
                var kValue = void 0;
                if (k in O) {
                    kValue = O[k];
                    callback.call(T, kValue, k, O);
                }
                k++;
            }
        };
    }

    if (typeof Array.prototype.isArray !== 'function') {
        Array.prototype.isArray = function (arg) {
            return Object.prototype.toString.call(arg) === '[object Array]';
        };
    }

    if (typeof Array.prototype.includes !== 'function') {
        Array.prototype.includes = function (searchElement, fromIndex) {
            'use strict';

            if (this === null) {
                throw new TypeError('"this" is null or not defined');
            }
            var o = Object(this),
                len = o.length >>> 0;
            if (len === 0) {
                return false;
            }
            var n = fromIndex | 0;
            var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            while (k < len) {
                if (o[k] === searchElement) {
                    return true;
                }
                k++;
            }
            return false;
        };
    }

    if (typeof Array.prototype.find !== 'function') {
        Array.prototype.find = function (predicate) {
            'use strict';

            if (this === null) {
                throw new TypeError('Array.prototype.find called on null or undefined');
            }
            if (typeof predicate !== 'function') {
                throw new TypeError('predicate must be a function');
            }
            var list = Object(this),
                length = list.length >>> 0,
                thisArg = arguments[1],
                value = void 0;

            for (var i = 0; i < length; i++) {
                value = list[i];
                if (predicate.call(thisArg, value, i, list)) {
                    return value;
                }
            }
            return undefined;
        };
    }

    if (typeof Array.prototype.findIndex !== 'function') {
        Array.prototype.findIndex = function (predicate) {
            if (this === null) {
                throw new TypeError('Array.prototype.findIndex called on null or undefined');
            }
            if (typeof predicate !== 'function') {
                throw new TypeError('predicate must be a function');
            }
            var list = Object(this),
                length = list.length >>> 0,
                thisArg = arguments[1],
                value = void 0;

            for (var i = 0; i < length; i++) {
                value = list[i];
                if (predicate.call(thisArg, value, i, list)) {
                    return i;
                }
            }
            return -1;
        };
    }

    if (typeof Array.prototype.compact !== 'function') {
        Array.prototype.compact = function () {
            var index = -1,
                length = this === null ? 0 : this.length,
                resIndex = 0,
                result = [];
            while (++index < length) {
                var value = this[index];
                if (value) {
                    result[resIndex++] = value;
                }
            }
            return result;
        };
    }

    if (typeof Array.prototype.insertOf !== 'function') {
        Array.prototype.insertOf = function (index, value) {
            if (this.length < index) {
                throw Error('index can not big than length!');
            }
            this.splice(index, 0, value);
        };
    }
}

/**
 * 作答完全状态
 */
var CompleteState = {
    UNANSWERED: 'UNANSWERED', //未作答
    PARTICAL_ANSWERED: 'PARTICAL_ANSWERED', //部分作答
    ALL_ANSWERED: 'ALL_ANSWERED' };

/**
 * 作答正误状态，历史原因，getResult重构之前统一使用以下状态
 */


/**
 * 答案类型
 */
var Cardinality = {
    SINGLE: 'single', //一道题只有一个正确答案，如单选、判断
    MULTIPLE: 'multiple', //一道题有多个答案，如多选，连线
    ORDERED: 'ordered' //一道题的答案必须严格按顺序匹配，如排序题、填空题
};

/**
 * 答案选项类型
 */
var BaseType = {
    STRING: 'string',
    MULTIPLE_STRING: 'multipleString', //多字符串，例如在顺序填空题中，如果正确答案为“铜锣烧|tls”，那么填写的答案为“铜锣烧”或则“tls”都认为是正确的，兼容qti
    BOOLEAN: 'boolean',
    FLOAT: 'float',
    INTEGER: 'integer',
    ARRAY: 'array',
    PAIR: 'pair',
    JSON: 'json'
};

/**
 * Qti 答案状态
 */
var QtiCompletionStatus = {
    INCOMPLETE: 'INCOMPLETE', //未作答
    COMPLETE: 'COMPLETE', //完成作答（目前没有使用）
    PASSED: 'PASSED', //答题正确
    FAILED: 'FAILED' //答题错误
};

//相关公共方法
var ServiceUtils = {
    /**
     * 深度克隆对象
     * 
     * @param {any} obj 
     * @returns 
     */
    deepClone: function deepClone(obj) {
        if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object') {
            return JSON.parse(JSON.stringify(obj));
        }
        return obj;
    }
};

/**
 * 适配正确答案模型
 * @param {*} correctAnswer 
 */
var parseCorrectAnswer = function parseCorrectAnswer(correctAnswer) {

    var correct = {
        baseType: BaseType.STRING, //默认都作为string类型处理
        cardinality: Cardinality.MULTIPLE,
        value: []
    };

    if (correctAnswer && correctAnswer.value) {
        correct.value = ServiceUtils.deepClone(correctAnswer.value);

        if (correctAnswer.baseType === 'multipleString') {
            correct.baseType = BaseType.MULTIPLE_STRING;
        }

        if (correctAnswer.cardinality === 'single') {
            correct.cardinality = Cardinality.SINGLE;
        } else if (correctAnswer.cardinality === 'ordered') {
            correct.cardinality = Cardinality.ORDERED;
        } else if (correctAnswer.cardinality === 'multiple') {
            correct.cardinality = Cardinality.MULTIPLE;
        }
    }
    return correct;
};

var QtiAdapter = {
    /**
     * 获取作答结果模型
     * 
     * @param {any} model 标准模型
     * @param {any} userAnswer 用户答案  
     * @returns 返回值 {
                answerState: true, //正确错误
                completeState: CompleteState.UNANSWERED, //是否作答
                unAnsweredCount: 0, //
                items: {}
            }
     */
    parseModel: function parseModel(qtiModel) {
        var items = [];

        var modelMap = qtiModel.modelMap,
            hintFeedback = qtiModel.hintFeedback || {},
            answerFeedback = qtiModel.answerFeedback || {},
            correctAnswer = qtiModel.correctAnswer,
            id = void 0,
            qtiItemModel = void 0,
            modelType = void 0,
            item = void 0,
            isTextEntry = true,
            //是否是填空题
        firstModelId = '';

        for (id in modelMap) {
            if (modelMap.hasOwnProperty(id)) {
                qtiItemModel = modelMap[id];
                modelType = qtiItemModel.modelType;
                if (!firstModelId) {
                    firstModelId = id;
                }
                if (modelType !== 'textEntryInteraction') {
                    isTextEntry = false;
                }
                item = {
                    id: id, //习题ID
                    qti: true,
                    type: modelType, //题目类型type
                    name: '', //题目名称
                    subjective: false, //是否主观题
                    hint: {
                        content: ''
                    },
                    analysis: {
                        content: ''
                    },
                    correctAnswer: {
                        cardinality: "", //答案类型
                        baseType: "", //答案项类型
                        value: [] //数组的形式存在
                    },
                    detail: {} //具体题目详细内容
                };

                if (hintFeedback[id] && hintFeedback[id].content !== undefined) {
                    item.hint.content = hintFeedback[id].content;
                }
                if (answerFeedback[id] && answerFeedback[id].content !== undefined) {
                    item.analysis.content = answerFeedback[id].content;
                }

                if (modelType === 'choiceInteraction_vote' || modelType === 'extendedTextInteraction' || modelType === 'drawingInteraction_drawing' || modelType === 'drawingInteraction' || modelType === 'drawingInteraction_handwrite' || modelType === 'choiceInteraction' && qtiItemModel.questionType === 'vote') {
                    item.subjective = true;
                }

                if (correctAnswer[id]) {
                    item.correctAnswer = parseCorrectAnswer(correctAnswer[id]);
                }
                item.detail = qtiItemModel;

                items.push(item);
            }
        }

        return items;
    },
    parseAnswerState: function parseAnswerState(answerState) {
        var result = {
            answerState: answerState.completionStatus === QtiCompletionStatus.PASSED, //正确错误
            items: {}
        },
            item = void 0,
            allUnAnswered = true,
            itemCount = answerState.responseVariable.length; //小题数量


        //Qti存在多题情况：填空题、选做题、复合题
        // TODO:答案为空时，是否是正确，需要确认
        answerState.responseVariable.forEach(function (model) {
            item = {
                id: model.identifier,
                unAnsweredCount: 0,
                answerState: model.state === QtiCompletionStatus.PASSED,
                completeState: CompleteState.ALL_ANSWERED,
                candidateResponse: ServiceUtils.deepClone(model.candidateResponse), //用户答案
                correctResponse: ServiceUtils.deepClone(model.correctResponse) //正确答案
            };

            var answeredCount = item.candidateResponse.filter(function (answer) {
                return answer !== '';
            }).length;

            item.unAnsweredCount = item.correctResponse.length - answeredCount;
            if (item.unAnsweredCount < 0) {
                item.unAnsweredCount = 0;
            }

            if (answeredCount === 0) {
                item.completeState = CompleteState.UNANSWERED;
            } else if (answeredCount === item.correctResponse.length || item.correctResponse.length === 0 && answeredCount > 0) {
                item.completeState = CompleteState.ALL_ANSWERED;
            } else {
                item.completeState = CompleteState.PARTICAL_ANSWERED;
            }

            if (item.completeState === CompleteState.UNANSWERED) {
                item.answerState = false;
            } else {
                allUnAnswered = false;
            }

            result.items[model.identifier] = item;
        });

        if (allUnAnswered) {
            result.answerState = false;
        }

        return result;
    },
    isQtiAnswerState: function isQtiAnswerState(answerState) {
        return !!(answerState && answerState.completionStatus && answerState.responseVariable);
    }
};

var CardinalityChecker = {
    /**
     * 比对单个答案是否正确
     * @param baseType 答案项类型
     * @param correctValue 正确答案
     * @param currentValue 用户答案
     * @returns {boolean}
     */
    checkOneValue: function checkOneValue(baseType, correctValue, currentValue) {
        //如果两个都是object直接进行全等判断
        if ((typeof correctValue === 'undefined' ? 'undefined' : _typeof(correctValue)) === 'object' && (typeof currentValue === 'undefined' ? 'undefined' : _typeof(currentValue)) === 'object') {
            correctValue = JSON.stringify(correctValue);
            currentValue = JSON.stringify(currentValue);
            return correctValue === currentValue;
        }

        switch (baseType) {
            case BaseType.STRING:
            case BaseType.BOOLEAN:
            case BaseType.FLOAT:
            case BaseType.INTEGER:
                return correctValue === currentValue;
            case BaseType.ARRAY:
            case BaseType.PAIR:
            case BaseType.JSON:
                return JSON.stringify(correctValue) === JSON.stringify(currentValue);
            default:
                //没有指定类型，则直接进行全等判断
                if ((typeof correctValue === 'undefined' ? 'undefined' : _typeof(correctValue)) === 'object' && (typeof currentValue === 'undefined' ? 'undefined' : _typeof(currentValue)) === 'object') {
                    correctValue = JSON.stringify(correctValue);
                    currentValue = JSON.stringify(currentValue);
                }
                return correctValue === currentValue;
        }
    },

    /**
     * 单个答案判断
     * 
     * @param {any} baseType 
     * @param {any} correctAnswerVal 
     * @param {any} userAnswerVal 
     * @returns 
     */
    single: function single(baseType, correctAnswerVal, userAnswerVal) {
        return this.checkOneValue(baseType, correctAnswerVal[0], userAnswerVal[0]);
    },

    /**
     * 答案顺序必须匹配
     * 
     * @param {any} baseType 
     * @param {any} correctAnswerVal 
     * @param {any} userAnswerVal 
     * @returns 
     */
    ordered: function ordered(baseType, correctAnswerVal, userAnswerVal) {
        var i = void 0,
            result = void 0,
            correctLength = correctAnswerVal.length;

        //长度必须相等
        if (correctLength !== userAnswerVal.length) {
            return false;
        }

        //顺序必须一致
        for (i = 0; i < correctLength; i++) {
            result = this.checkOneValue(baseType, correctAnswerVal[i], userAnswerVal[i]);
            //只要有一个不匹配，答案错误
            if (result === false) {
                break;
            }
        }
        return result;
    },

    /**
     * 答案顺序可不匹配
     * 
     * @param {any} baseType 
     * @param {any} correctAnswerVal 
     * @param {any} userAnswerVal 
     * @returns 
     */
    multiple: function multiple(baseType, correctAnswerVal, userAnswerVal) {
        var i = void 0,
            result = void 0,
            correctLength = correctAnswerVal.length,
            correctItem = void 0,
            tempAnswer = userAnswerVal.slice();

        //长度必须相等
        if (correctLength !== userAnswerVal.length) {
            return false;
        }

        //顺序可不一致
        for (i = 0; i < correctLength; i++) {
            correctItem = correctAnswerVal[i];
            var whileCount = 0;
            var answerLength = tempAnswer.length;
            while (tempAnswer.length) {
                var temp = tempAnswer.shift();
                result = this.checkOneValue(baseType, correctItem, temp);
                if (result) {
                    break;
                } else {
                    tempAnswer.push(temp);
                }
                whileCount++;
                if (whileCount >= answerLength) {
                    result = false;
                    break;
                }
            }
            if (result === false) {
                break;
            }
        }
        return result;
    },

    getCompleteState: function getCompleteState(answeredCount, correctAnswerLength) {

        var unAnsweredCount = correctAnswerLength - answeredCount;
        //正确答案可能为空
        if (unAnsweredCount < 0) {
            unAnsweredCount = 0;
        }

        if (answeredCount === 0) {
            return CompleteState.UNANSWERED;
        } else if (answeredCount === correctAnswerLength) {
            return CompleteState.ALL_ANSWERED;
        } else {
            return CompleteState.PARTICAL_ANSWERED;
        }
    },
    checkAnswer: function checkAnswer(correctAnswer, userAnswerVal) {
        var correctVal = correctAnswer.value || [],
            correctLength = correctVal.length,
            cardinality = correctAnswer.cardinality,
            baseType = correctAnswer.baseType,
            result = void 0;

        if (!correctAnswer || !correctLength) {
            //没有正确答案，默认认为做对
            result = true;
        } else if (userAnswerVal.length !== correctLength) {
            //用户答案的长度和正确答案的长度不一致，答题错误
            result = false;
        } else {
            result = this[cardinality](baseType, correctVal, userAnswerVal);
        }
        return result;
    }

};

//返回作答项结果模型
var State = {
    getNormalItemResult: function getNormalItemResult(item, correctAnswer, userItemAnswer) {
        var correctAnswerVal = correctAnswer && correctAnswer.value || [],
            userAnswerVal = userItemAnswer.value || [];

        var itemResult = {
            id: item.id,
            unAnsweredCount: 0, //未作答空
            answerState: false,
            completeState: CompleteState.ALL_ANSWERED,
            candidateResponse: ServiceUtils.deepClone(userAnswerVal), //用户答案
            correctResponse: ServiceUtils.deepClone(correctAnswerVal) //正确答案
        };

        //未作答数，排除空字符串
        var answeredCount = userAnswerVal.filter(function (val) {
            return val !== '';
        }).length;

        //未完成数
        if (correctAnswerVal.length !== 0) {
            itemResult.unAnsweredCount = correctAnswerVal.length - answeredCount;
        }

        //完成状态
        if (answeredCount === 0) {
            itemResult.completeState = CompleteState.UNANSWERED;
        } else if (answeredCount < correctAnswerVal.length) {
            itemResult.completeState = CompleteState.PARTICAL_ANSWERED;
        }

        //正误状态
        if (userItemAnswer.answerState === true || userItemAnswer.answerState === false) {
            //自带结果，直接使用用户作答结果
            itemResult.answerState = userItemAnswer.answerState;
        } else if ((!correctAnswer || !correctAnswer.value || !correctAnswerVal.length) && item.getModel) {
            //小题还未加载
            itemResult.answerState = false;
        } else if (item.subjective) {
            //主观题默认正确
            itemResult.answerState = true;
        } else {
            //判断用户作答情况
            itemResult.answerState = CardinalityChecker.checkAnswer(correctAnswer, userAnswerVal);
        }
        return itemResult;
    },
    getQtiItemResult: function getQtiItemResult(qtiState) {
        // let itemId = Object.keys(qtiState)[0];
        var answerState = QtiAdapter.parseAnswerState(qtiState);
        var ids = Object.keys(answerState.items);
        var itemResult = answerState.items[ids[0]];
        return itemResult;
    },
    getItemState: function getItemState(item, userAnswer) {
        var correctAnswer = item.correctAnswer || {},
            correctAnswerVal = correctAnswer && correctAnswer.value || [],
            userItemAnswer = userAnswer.value || [],
            itemResult = void 0;

        if (QtiAdapter.isQtiAnswerState(userAnswer)) {
            //复合类习题内不会嵌套Qti的复合题，直接单做单题处理即可
            itemResult = this.getQtiItemResult(userAnswer);
        } else {
            itemResult = this.getNormalItemResult(item, correctAnswer, userAnswer);
        }
        itemResult.id = item.id;

        return itemResult;
    },
    isQtiState: function isQtiState(userAnswer) {
        var allQti = true;
        for (var id in userAnswer) {
            if (userAnswer.hasOwnProperty(id)) {
                allQti = QtiAdapter.isQtiAnswerState(userAnswer[id]);
                if (!allQti) {
                    break;
                }
            }
        }
        return allQti;
    },
    getAnswerState: function getAnswerState(model, userAnswer) {

        var that = this,
            items = model.items || [],
            itemsCount = items.length || 1,
            result = {
            answerState: true, //正确错误
            items: {}
        };

        var ids = Object.keys(userAnswer);
        //qti复合题，只有一个Qti题型时（一个Qti实例加载出来的习题，包含Qti的复合、填空、选做）
        if (items.length > 0 && ids.length === 1 && this.isQtiState(userAnswer)) {
            return QtiAdapter.parseAnswerState(userAnswer[ids[0]]);
        }

        if (items.length === 0) {
            if (!userAnswer[model.id]) {
                throw new Error('答案id和模型id不匹配', userAnswer, model.id);
            }
            //单题
            result.items[model.id] = that.getItemState(model, userAnswer[model.id] || {});
        } else {
            //普通复合题
            items.forEach(function (item) {
                var id = item.id;
                if (!userAnswer[item.id]) {
                    throw new Error('答案id和模型id不匹配', userAnswer, id);
                }
                result.items[id] = that.getItemState(item, userAnswer[id] || {});
            });
        }

        var resultItem = void 0;

        for (var id in result.items) {
            if (!result.items.hasOwnProperty(id)) {
                continue;
            }
            resultItem = result.items[id];

            //只要有一小题错误，就认为整道题错误
            if (resultItem.answerState === false) {
                result.answerState = false;
            }
        }

        return result;
    },
    getDefaultState: function getDefaultState(model) {
        var answerState = {
            answerState: false,
            items: {}
        };

        // let model = this.getQuestionModel();
        if (model.items && model.items.length > 0) {
            model.items.forEach(function (item) {
                answerState.items[item.id] = {
                    id: item.id,
                    unAnsweredCount: 0, //未作答空
                    answerState: false,
                    completeState: CompleteState.UNANSWERED,
                    candidateResponse: [], //用户答案
                    correctResponse: ServiceUtils.deepClone(item.correctAnswer) //正确答案
                };
            }, this);
        } else {
            answerState.items[model.id] = {
                id: model.id,
                unAnsweredCount: 0, //未作答空
                answerState: false,
                completeState: CompleteState.UNANSWERED,
                candidateResponse: [], //用户答案
                correctResponse: [] //正确答案
            };
        }
        return answerState;
    }
};

var AnswerStateChecker = {
    /**
     * 获取作答结果模型
     * 
     * @param {any} model 标准模型
     * @param {any} userAnswer 用户答案  
     * @returns 返回值 {
                answerState: true, //正确错误
                completeState: CompleteState.UNANSWERED, //是否作答
                unAnsweredCount: 0, //
                items: {}
            }
     */
    getCheckState: function getCheckState(model, userAnswer) {
        return State.getAnswerState(model, userAnswer);
    },

    /**
     * 
     * 获取默认情况下的作答结果模型
     * 
     * @param {any} model 
     * @returns 
     */
    getDefaultState: function getDefaultState(model) {
        return State.getDefaultState(model);
    }
};

//相关公共方法

var Event = function () {
    function Event() {
        classCallCheck(this, Event);

        this._eventHandler = {};
    }

    createClass(Event, [{
        key: "trigger",
        value: function trigger() {
            //将参数转换为数组
            var arg = Array.prototype.slice.apply(arguments, [0]);
            //取第一个，并从数组中删除，事件key
            var type = arg.shift();
            if (type) {
                type = type.toLowerCase();
            }
            if (!this._eventHandler || !this._eventHandler[type]) {
                return false;
            }
            var handlers = this._eventHandler[type];
            handlers.forEach(function (handler) {
                handler.cb.apply(handler.domain || this, arg);
            });
            return true;
        }
    }, {
        key: "on",
        value: function on(type, callback, domain) {
            if (!this._eventHandler[type]) {
                this._eventHandler[type] = [];
            }
            this._eventHandler[type].push({
                cb: callback,
                domain: domain
            });
            return true;
        }
    }, {
        key: "off",
        value: function off(type, callback, domain) {
            var handlers = this._eventHandler[type];
            if (handlers && handlers.length > 0) {
                var len = handlers.length;
                var handler;
                for (var i = 0; i < len; i++) {
                    handler = handlers[i];
                    if (handler && callback === handler.cb) {
                        if (domain && domain !== handler.domain) {
                            continue;
                        }
                        handlers.splice(i, 1);
                        i--;
                        len--;
                    }
                }
            }
            if (handlers && handlers.length === 0) {
                delete this._eventHandler[type];
            }
        }
    }]);
    return Event;
}();

/**
 * 公共service基类
 */

var notIplementException = function notIplementException() {
    throw new Error('该方法还未实现');
};

var BaseService = function () {
    function BaseService(id) {
        classCallCheck(this, BaseService);

        this.questionId = id;
        this.answerState = null;
        this.userAnswer = null;
        this.event = new Event();
    }

    /**
     * 获取标准的题型model
     * @memberof BaseService
     */


    createClass(BaseService, [{
        key: 'getQuestionModel',
        value: function getQuestionModel() {
            notIplementException();
        }

        /**
         * 获取用户作答状态
         * 
         * @memberof BaseService
         */

    }, {
        key: 'getAnswerState',
        value: function getAnswerState() {
            this.event.trigger('beforeGetAnswerState');
            var answerState = this.answerState;
            if (!answerState) {
                return AnswerStateChecker.getDefaultState(this.getQuestionModel());
            }
            return ServiceUtils.deepClone(answerState);
        }

        /**
         * 
         * 获取用户答案
         * 
         * @memberof BaseService
         */

    }, {
        key: 'getAnswer',
        value: function getAnswer() {
            return ServiceUtils.deepClone(this.userAnswer);
        }

        /**
         * 状态变更通知
         * 
         * @param {any} name 事件名  answerChange(用户作答变更)
         * @param {any} data 事件数据 
         * @memberof BaseService
         */

    }, {
        key: 'trigger',
        value: function trigger(name, data) {
            var that = this;
            name = name.toLowerCase();
            if (name === 'answerchange') {
                this.userAnswer = data;
                this.answerState = AnswerStateChecker.getCheckState(this.getQuestionModel(), data);
            }
            this.event.trigger(name, data);
        }
    }, {
        key: 'on',
        value: function on(name, callback) {
            this.event.on(name.toLowerCase(), callback);
        }
    }, {
        key: 'off',
        value: function off(name, callback) {
            this.event.off(name.toLowerCase(), callback);
        }

        /**
         * 返回当前题目提示类型
         * 
         * @memberof BaseService
         * @return  //SIMPLE,MULTBLANK,MULTQUESTION,PARTICAL,提示类型对应题型A,B,C,D
         */

    }, {
        key: 'getTipType',
        value: function getTipType() {
            notIplementException();
        }

        /**
         * 用于子类多用户作答结果模型的扩展
         * @param {any} result 作答模型
         * @memberof BaseService
         */

    }, {
        key: 'extendResult',
        value: function extendResult(result) {
            notIplementException();
        }

        /**
         * 
         * 获取信息基础信息 
         * @memberof BaseService
         */

    }, {
        key: 'getQuestionInfo',
        value: function getQuestionInfo() {
            notIplementException();
        }

        /**
         * 显示用户、或正确答案
         * 
         * @param {any} type  ‘user/correct’ 
         * @param {any} specialAnswer 用户答案，可不传
         * @memberof BaseService
         */

    }, {
        key: 'showAnswer',
        value: function showAnswer(type, specialAnswer) {
            notIplementException();
        }

        /**
         * 锁定题目，不可作答
         * @memberof BaseService
         */

    }, {
        key: 'lockQuestion',
        value: function lockQuestion() {
            notIplementException();
        }

        /**
         * 解锁题目
         * @memberof BaseService
         */

    }, {
        key: 'unlockQuestion',
        value: function unlockQuestion() {
            notIplementException();
        }

        /**
         * 结束题目
         * @memberof BaseService
         */

    }, {
        key: 'finishQuestion',
        value: function finishQuestion() {
            notIplementException();
        }

        /**
         * 重置题目
         * @memberof BaseService
         */

    }, {
        key: 'resetQuestion',
        value: function resetQuestion() {
            notIplementException();
        }

        /**
         * 显示用户作答反馈提示
         * @memberof BaseService
         */

    }, {
        key: 'showResultHint',
        value: function showResultHint() {
            notIplementException();
        }
    }], [{
        key: 'parseQtiModel',
        value: function parseQtiModel(qtiModel) {
            return QtiAdapter.parseModel(qtiModel);
        }
    }]);
    return BaseService;
}();

(function (self) {
    typescriptPolyFill();
    arrayPolyFill();
    stringPolyFill();
    //Set export class
    if (!self.Midware) self.Midware = Midware$1;
    if (!self.ConstVariable) self.ConstVariable = self.Midware.ConstVariable = ConstVariable$1;
    if (!self.CommonClass) self.CommonClass = self.Midware.CommonClass = CommonClass;
    if (!self.SceneClass) self.SceneClass = self.Midware.SceneClass = SceneClass;
    if (!self.CommonController) self.CommonController = self.Midware.CommonController = CommonController;
    if (!self.CommonService) self.CommonService = self.Midware.CommonService = BaseService;
    //初始化组件库
    initSwarm();
})(typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : window);

})));
